Exemplo n.º 1
0
    public void BuildSceneMeshObject()
    {
        if (_mesh == null)
        {
            _mesh = new Mesh();
        }
        MB_MeshBaker mom  = this;
        GameObject   mesh = mom.gameObject;
        MeshFilter   mf   = mesh.GetComponent <MeshFilter>();

        if (mf == null)
        {
            mf = mesh.AddComponent <MeshFilter>();
        }
        MeshRenderer mr = mesh.GetComponent <MeshRenderer>();

        if (mr == null)
        {
            mr = mesh.AddComponent <MeshRenderer>();
        }
        if (mom.doMultiMaterial)
        {
            Material[] sharedMats = new Material[mom.resultMaterials.Length];
            for (int i = 0; i < sharedMats.Length; i++)
            {
                sharedMats[i] = mom.resultMaterials[i].combinedMaterial;
            }
            mr.sharedMaterials = sharedMats;
        }
        else
        {
            mr.material = mom.resultMaterial;
        }
        mf.mesh = _mesh;
    }
    bool validateMultipleMaterials()
    {
        MB_MeshBaker mom = (MB_MeshBaker)target;

        MB_MultiMaterial[] rs          = mom.resultMaterials;
        List <Material>    allSource   = new List <Material>();
        List <Material>    allCombined = new List <Material>();

        for (int i = 0; i < rs.Length; i++)
        {
            if (allCombined.Contains(rs[i].combinedMaterial))
            {
                Debug.LogError("There are duplicate combined materials in the combined materials list");
                return(false);
            }
            for (int j = 0; j < rs[i].sourceMaterials.Count; j++)
            {
                if (rs[i].sourceMaterials[j] == null)
                {
                    Debug.LogError("There are nulls in the list of source materials");
                    return(false);
                }
                if (allSource.Contains(rs[i].sourceMaterials[j]))
                {
                    Debug.LogError("There are duplicate source materials in the combined materials list");
                    return(false);
                }
                allSource.Add(rs[i].sourceMaterials[j]);
            }
            allCombined.Add(rs[i].combinedMaterial);
        }
        return(true);
    }
    void bakeTexturesOnly()
    {
        if (!doCombinedValidate(MB_ObjsToCombineTypes.prefabOnly))
        {
            return;
        }

        MB_AtlasesAndRects[] mAndAs = null;
        try{
            MB_MeshBaker mbd = (MB_MeshBaker)target;
            mAndAs = mbd.CreateAtlases(updateProgressBar);
            if (mAndAs != null)
            {
                for (int i = 0; i < mAndAs.Length; i++)
                {
                    MB_AtlasesAndRects mAndA = mAndAs[i];
                    updateProgressBar("Created mesh saving assets", .6f);
                    Material resMat = mbd.resultMaterial;
                    if (mbd.doMultiMaterial)
                    {
                        resMat = mbd.resultMaterials[i].combinedMaterial;
                    }
                    saveAtlasesToAssetDatabase(mAndA, resMat);
                    meshBaker.SetIsDifferentCacheDirty();
                    updateProgressBar("Replacing prefab", .7f);
                }
            }
        } catch (Exception e) {
            Debug.LogError(e);
        } finally {
            EditorUtility.ClearProgressBar();
            if (mAndAs != null)
            {
                for (int j = 0; j < mAndAs.Length; j++)
                {
                    MB_AtlasesAndRects mAndA = mAndAs[j];
                    if (mAndA != null && mAndA.atlases != null)
                    {
                        for (int i = 0; i < mAndA.atlases.Length; i++)
                        {
                            if (mAndA.atlases[i] != null)
                            {
                                MB_Utility.Destroy(mAndA.atlases[i]);
                            }
                        }
                    }
                }
            }
        }
    }
    //todo create prefab should handle multi material
    void buildSceneMeshObject(GameObject root, Mesh m)
    {
        MB_MeshBaker mom = (MB_MeshBaker)target;
        GameObject   mesh;
        Transform    mt = null;

        foreach (Transform t in root.transform)
        {
            if (t.name.EndsWith("-mesh"))
            {
                mt = t;
            }
        }
        if (mt == null)
        {
            mesh = new GameObject(target.name + "-mesh");
        }
        else
        {
            mesh = mt.gameObject;
        }
        MeshFilter mf = mesh.GetComponent <MeshFilter>();

        if (mf == null)
        {
            mf = mesh.AddComponent <MeshFilter>();
        }
        MeshRenderer mr = mesh.GetComponent <MeshRenderer>();

        if (mr == null)
        {
            mr = mesh.AddComponent <MeshRenderer>();
        }
        if (mom.doMultiMaterial)
        {
            Material[] sharedMats = new Material[mom.resultMaterials.Length];
            for (int i = 0; i < sharedMats.Length; i++)
            {
                sharedMats[i] = mom.resultMaterials[i].combinedMaterial;
            }
            mr.sharedMaterials = sharedMats;
        }
        else
        {
            mr.material = mom.resultMaterial;
        }
        mf.mesh = m;
        mesh.transform.parent = root.transform;
    }
    bool validateSubmeshOverlap()
    {
        MB_MeshBaker mom = (MB_MeshBaker)target;

        for (int i = 0; i < mom.objsToMesh.Count; i++)
        {
            Mesh m = MB_Utility.GetMesh(mom.objsToMesh[i]);
            if (MB_Utility.doSubmeshesShareVertsOrTris(m) != 0)
            {
                Debug.LogError("Object " + mom.objsToMesh[i] + " in the list of objects to combine has overlapping submeshes. This object can only be combined with objects that use the exact same set of textures. There may be other undesirable side affects as well.");
                return(true);
            }
        }
        return(true);
    }
    void saveMeshToAssetDatabase(Mesh mesh)
    {
        MB_MeshBaker mom       = (MB_MeshBaker)target;
        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;
        }
        string baseName    = System.IO.Path.GetFileNameWithoutExtension(prefabPth);
        string folderPath  = prefabPth.Substring(0, prefabPth.Length - baseName.Length - 7);
        string newFilename = folderPath + baseName + "-mesh.asset";

        AssetDatabase.CreateAsset(mesh, newFilename);
    }
    void rebuildPrefab(MB_AtlasesAndRects[] ms, Mesh mesh)
    {
        MB_MeshBaker mom = (MB_MeshBaker)target;

        if (mom.resultPrefab == null)
        {
            Debug.LogError("Prefab to store result did not exist.");
        }
        GameObject rootGO = (GameObject)PrefabUtility.InstantiatePrefab(mom.resultPrefab);

        buildSceneMeshObject(rootGO, mesh);

        string prefabPth = AssetDatabase.GetAssetPath(mom.resultPrefab);

        PrefabUtility.ReplacePrefab(rootGO, AssetDatabase.LoadAssetAtPath(prefabPth, typeof(GameObject)), ReplacePrefabOptions.ConnectToPrefab);
        mom.resultPrefab = (GameObject)AssetDatabase.LoadAssetAtPath(prefabPth, typeof(GameObject));
        DestroyImmediate(rootGO);
    }
    void createNewPrefab(string pth)
    {
        string baseName   = System.IO.Path.GetFileNameWithoutExtension(pth);
        string folderPath = pth.Substring(0, pth.Length - baseName.Length - 7);
        string matName    = folderPath + baseName + "-mat.mat";

        AssetDatabase.CreateAsset(new Material(Shader.Find("Diffuse")), matName);
        UnityEngine.Object prefabAsset = PrefabUtility.CreateEmptyPrefab(pth);

        MB_MeshBaker mom    = (MB_MeshBaker)target;
        GameObject   rootGO = new GameObject("combinedMesh-" + mom.name);

        PrefabUtility.ReplacePrefab(rootGO, prefabAsset, ReplacePrefabOptions.ConnectToPrefab);

        DestroyImmediate(rootGO);
        mom.resultMaterial = (Material)AssetDatabase.LoadAssetAtPath(matName, typeof(Material));
        mom.resultPrefab   = (GameObject)AssetDatabase.LoadAssetAtPath(pth, typeof(GameObject));

        AssetDatabase.Refresh();
    }
    public override void OnInspectorGUI()
    {
        meshBaker.Update();

        showInstructions = EditorGUILayout.Foldout(showInstructions, "Instructions:");
        if (showInstructions)
        {
            EditorGUILayout.HelpBox("1. Create empty assets for result materials and (if needed) result prefab.\n\n" +
                                    "2. Select shader on result materials.\n\n" +
                                    "3. Add scene objects or prefabs to combine. For best results these should use the same shader as result material.\n\n" +
                                    "4. Select an output option.\n\n" +
                                    "5. Bake objects.\n\n" +
                                    "6. Look at warnings/errors in console. Decide if action needs to be taken.\n\n" +
                                    "5. Use the combined/adjusted meshes.\n\n" +
                                    "7. (optional) Disable renderers in source objects.\n\n" +
                                    "8. (optional) Remove the MeshBaker object. You may want to keep it for easy re-baking if something changes in the source objects.", UnityEditor.MessageType.None);

            EditorGUILayout.Separator();
        }

        MB_MeshBaker mom = (MB_MeshBaker)target;

        EditorGUILayout.LabelField("Options", EditorStyles.boldLabel);
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.PropertyField(fixOutOfBoundsUVs, fixOutOfBoundsGUIContent);
        EditorGUILayout.PropertyField(doMultiMaterial, new GUIContent("Multiple Combined Materials"));
        EditorGUILayout.EndHorizontal();
        EditorGUILayout.PropertyField(atlasPadding, new GUIContent("Atlas Padding"));
        EditorGUILayout.PropertyField(resizePowerOfTwoTextures, resizePowerOfTwoGUIContent);
        EditorGUILayout.PropertyField(customShaderPropNames, customShaderPropertyNamesGUIContent, true);

        if (mom.doMultiMaterial)
        {
            MB_EditorUtil.DrawSeparator();
            EditorGUILayout.LabelField("Source Material To Combined Mapping", EditorStyles.boldLabel);
            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();
                    EditorGUILayout.LabelField("---------- submesh:" + i);
                    EditorGUILayout.Separator();
                    SerializedProperty resMat = resultMaterials.GetArrayElementAtIndex(i);
                    EditorGUILayout.PropertyField(resMat.FindPropertyRelative("combinedMaterial"));
                    SerializedProperty sourceMats = resMat.FindPropertyRelative("sourceMaterials");
                    EditorGUILayout.PropertyField(sourceMats, true);
                }
            }
        }
        else
        {
            MB_EditorUtil.DrawSeparator();
            EditorGUILayout.LabelField("Combined Material", EditorStyles.boldLabel);
            EditorGUILayout.PropertyField(resultMaterial, new GUIContent("Combined Mesh Material"));
        }

        MB_EditorUtil.DrawSeparator();
        EditorGUILayout.LabelField("Objects To Be Combined", EditorStyles.boldLabel);
        if (GUILayout.Button(openToolsWindowLabelContent))
        {
            MB_MeshBakerEditorWindow mmWin = (MB_MeshBakerEditorWindow)EditorWindow.GetWindow(typeof(MB_MeshBakerEditorWindow));
            mmWin.target = (MB_MeshBaker)target;
        }
        EditorGUILayout.PropertyField(objsToMesh, new GUIContent("Objects To Be Combined"), true);
        MB_EditorUtil.DrawSeparator();

        EditorGUILayout.Separator();
        mom.resultPrefab = (GameObject)EditorGUILayout.ObjectField("Combined Mesh Prefab", mom.resultPrefab, typeof(GameObject), false);
        EditorGUILayout.PropertyField(outputOption, outputOptionGUIContent);
        if (GUILayout.Button("Bake"))
        {
            if (mom.outputOption == MB_OutputOptions.bakeIntoPrefab)
            {
                bakeMeshesIntoPrefab();
            }
            else if (mom.outputOption == MB_OutputOptions.bakeMeshsInPlace)
            {
                bakeMeshesInPlace();
            }
            else if (mom.outputOption == MB_OutputOptions.bakeTextureAtlasesOnly)
            {
                bakeTexturesOnly();
            }
        }
        EditorGUILayout.Separator();


        MB_EditorUtil.DrawSeparator();
        EditorGUILayout.LabelField("Utilities", EditorStyles.boldLabel);
        if (GUILayout.Button(createPrefabAndMaterialLabelContent))
        {
            string newPrefabPath = EditorUtility.SaveFilePanelInProject("Prefab name", "", "prefab", "Enter a name for the combined mesh prefab");
            if (newPrefabPath != null)
            {
                createNewPrefab(newPrefabPath);
            }
        }
        string enableRenderersLabel;

        if (mom.disableSourceRenderers)
        {
            enableRenderersLabel = "Disable Renderers On Combined Objects";
        }
        else
        {
            enableRenderersLabel = "Enable Renderers On Combined Objects";
        }
        if (GUILayout.Button(enableRenderersLabel))
        {
            mom.disableSourceRenderers = !mom.disableSourceRenderers;
            mom.EnableDisableSourceObjectRenderers(mom.disableSourceRenderers);
        }
        meshBaker.ApplyModifiedProperties();
    }
Exemplo n.º 10
0
    void bakeMeshesInPlace()
    {
        MB_MeshBaker mom = (MB_MeshBaker)target;

        MB_AtlasesAndRects[] mAndAs = null;
        Mesh mesh;

        if (!doCombinedValidate(MB_ObjsToCombineTypes.prefabOnly))
        {
            return;
        }

        try{
            mom.DestroyMesh();
            mAndAs = mom.CreateAtlases(updateProgressBar);
            if (mAndAs != null)
            {
                for (int i = 0; i < mAndAs.Length; i++)
                {
                    MB_AtlasesAndRects mAndA  = mAndAs[i];
                    Material           resMat = mom.resultMaterial;
                    if (mom.doMultiMaterial)
                    {
                        resMat = mom.resultMaterials[i].combinedMaterial;
                    }
                    saveAtlasesToAssetDatabase(mAndA, resMat);
                }
                GameObject[] objs = new GameObject[1];
                for (int i = 0; i < mom.objsToMesh.Count; i++)
                {
                    objs[0] = mom.objsToMesh[i];
                    mesh    = mom.AddDeleteGameObjects(objs, null, false);
                    if (mesh != null)
                    {
                        mom.ApplyAll();
                        MeshFilter mf = objs[0].GetComponent <MeshFilter>();
                        if (mf != null && mf.sharedMesh != null)
                        {
                            string baseName, folderPath, newFilename;
                            string pth = AssetDatabase.GetAssetPath(mf.sharedMesh);
                            if (pth != null && pth.Length != 0)
                            {
                                baseName    = System.IO.Path.GetFileNameWithoutExtension(pth);
                                folderPath  = System.IO.Path.GetDirectoryName(pth);
                                newFilename = System.IO.Path.Combine(folderPath, baseName + "_MB.asset");
                            }
                            else                                           //try to get the name from prefab
                            {
                                pth = AssetDatabase.GetAssetPath(objs[0]); //get prefab name
                                if (pth != null && pth.Length != 0)
                                {
                                    baseName    = System.IO.Path.GetFileNameWithoutExtension(pth);
                                    folderPath  = System.IO.Path.GetDirectoryName(pth);
                                    newFilename = System.IO.Path.Combine(folderPath, baseName + "_" + objs[0].name + "_MB.asset");
                                }
                                else                                     //save in root
                                {
                                    newFilename = System.IO.Path.Combine("Assets", objs[0].name + "mesh_MB.asset");
                                }
                            }
                            updateProgressBar("Created mesh saving asset " + newFilename, .6f);
                            if (newFilename != null && newFilename.Length != 0)
                            {
                                Debug.Log("Created mesh with adjusted UVs at: " + newFilename);
                                AssetDatabase.CreateAsset(mesh, newFilename);
                            }
                            else
                            {
                                Debug.LogWarning("Could not save mesh for " + objs[0].name);
                            }
                        }
                    }
                    mom.DestroyMesh();
                }
            }
        } catch (Exception e) {
            Debug.LogError(e);
        } finally {
            EditorUtility.ClearProgressBar();
            mom.DestroyMesh();
            if (mAndAs != null)
            {
                for (int j = 0; j < mAndAs.Length; j++)
                {
                    MB_AtlasesAndRects mAndA = mAndAs[j];
                    if (mAndA != null && mAndA.atlases != null)
                    {
                        for (int i = 0; i < mAndA.atlases.Length; i++)
                        {
                            if (mAndA.atlases[i] != null)
                            {
                                MB_Utility.Destroy(mAndA.atlases[i]);
                            }
                        }
                    }
                }
            }
        }
    }
Exemplo n.º 11
0
    void bakeMeshesIntoPrefab()
    {
        MB_MeshBaker mom = (MB_MeshBaker)target;

        MB_AtlasesAndRects[] mAndAs = null;
        Mesh mesh;

        if (!doCombinedValidate(MB_ObjsToCombineTypes.sceneObjOnly))
        {
            return;
        }
        if (mom.resultPrefab == null)
        {
            Debug.LogError("Need to set the result prefab field.");
            return;
        }
        try{
            mom.DestroyMesh();
            mAndAs = mom.CreateAtlases(updateProgressBar);
            if (mAndAs != null)
            {
                for (int i = 0; i < mAndAs.Length; i++)
                {
                    MB_AtlasesAndRects mAndA  = mAndAs[i];
                    Material           resMat = mom.resultMaterial;
                    if (mom.doMultiMaterial)
                    {
                        resMat = mom.resultMaterials[i].combinedMaterial;
                    }
                    saveAtlasesToAssetDatabase(mAndA, resMat);
                }
                mesh = mom.AddDeleteGameObjects(mom.objsToMesh.ToArray(), null, false, true);
                if (mesh != null)
                {
                    mom.ApplyAll();
                    updateProgressBar("Created mesh saving assets", .6f);
                    saveMeshToAssetDatabase(mesh);
                    updateProgressBar("Replacing prefab", .7f);
                    rebuildPrefab(mAndAs, mesh);
                }
            }
        } catch (Exception e) {
            Debug.LogError(e);
        } finally {
            EditorUtility.ClearProgressBar();
            mom.DestroyMesh();
            if (mAndAs != null)
            {
                for (int j = 0; j < mAndAs.Length; j++)
                {
                    MB_AtlasesAndRects mAndA = mAndAs[j];
                    if (mAndA != null && mAndA.atlases != null)
                    {
                        for (int i = 0; i < mAndA.atlases.Length; i++)
                        {
                            if (mAndA.atlases[i] != null)
                            {
                                MB_Utility.Destroy(mAndA.atlases[i]);
                            }
                        }
                    }
                }
            }
        }
    }
Exemplo n.º 12
0
    bool doCombinedValidate(MB_ObjsToCombineTypes objToCombineType)
    {
        MB_MeshBaker mom = (MB_MeshBaker)target;

        for (int i = 0; i < mom.objsToMesh.Count; i++)
        {
            if (mom.objsToMesh[i] == null)
            {
                Debug.LogError("The list of objects to combine contains nulls.");
                return(false);
            }
            for (int j = i + 1; j < mom.objsToMesh.Count; j++)
            {
                if (mom.objsToMesh[i] == mom.objsToMesh[j])
                {
                    Debug.LogError("The list of objects to combine contains duplicates.");
                    return(false);
                }
            }
        }

        if (mom.doMultiMaterial)
        {
            if (!validateMultipleMaterials())
            {
                return(false);
            }
            if (!validateSubmeshOverlap())             //only warns currently
            {
                return(false);
            }
        }
        else
        {
            if (mom.resultMaterial == null)
            {
                Debug.LogError("Please assign a result material. The combined mesh will use this material.");
                return(false);
            }
        }
        if (mom.objsToMesh == null || mom.objsToMesh.Count == 0)
        {
            Debug.LogError("No meshes to combine. Please assign some meshes to combine.");
            return(false);
        }
        if (mom.atlasPadding < 0)
        {
            Debug.LogError("Atlas padding must be zero or greater.");
            return(false);
        }

        for (int i = 0; i < mom.objsToMesh.Count; i++)
        {
            UnityEditor.PrefabType pt = UnityEditor.PrefabUtility.GetPrefabType(mom.objsToMesh[i]);
            if (pt == UnityEditor.PrefabType.None ||
                pt == UnityEditor.PrefabType.PrefabInstance ||
                pt == UnityEditor.PrefabType.ModelPrefabInstance ||
                pt == UnityEditor.PrefabType.DisconnectedPrefabInstance ||
                pt == UnityEditor.PrefabType.DisconnectedModelPrefabInstance)
            {
                // these are scene objects
                if (objToCombineType == MB_ObjsToCombineTypes.prefabOnly)
                {
                    Debug.LogWarning("The list of objects to combine contains scene objects. You probably want prefabs." + mom.objsToMesh[i] + " is a scene object");
                }
            }
            else if (objToCombineType == MB_ObjsToCombineTypes.sceneObjOnly)
            {
                //these are prefabs
                Debug.LogError("The list of objects to combine contains prefab objects. You probably want scene objects." + mom.objsToMesh[i] + " is a prefab object");
            }
        }
        return(true);
    }