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();
    }
    private static void ProcessPrefabRowReplaceTargetPrefab(MB3_BatchPrefabBaker pb, MB3_BatchPrefabBaker.MB3_PrefabBakerRow pr, MB2_TextureBakeResults tbr, List <UnityTransform> unityTransforms, MB3_MeshBaker mb)
    {
        if (pb.LOG_LEVEL >= MB2_LogLevel.info)
        {
            Debug.Log("==== Processing Source Prefab " + pr.sourcePrefab);
        }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        if (pb.LOG_LEVEL >= MB2_LogLevel.debug)
        {
            Debug.Log("Destroyed " + numDestroyed + " meshes");
        }
        AssetDatabase.SaveAssets();
        //--------------------------
    }
Ejemplo n.º 3
0
        public void PopulatePrefabRowsFromTextureBaker(MB3_BatchPrefabBaker prefabBaker)
        {
            MB3_TextureBaker  texBaker   = prefabBaker.GetComponent <MB3_TextureBaker>();
            List <GameObject> newPrefabs = new List <GameObject>();
            List <GameObject> gos        = texBaker.GetObjectsToCombine();

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

                if (obj != null && obj is GameObject)
                {
                    if (!newPrefabs.Contains((GameObject)obj))
                    {
                        newPrefabs.Add((GameObject)obj);
                    }
                }
                else
                {
                    Debug.LogWarning(String.Format("Object {0} did not have a prefab", gos[i]));
                }
            }

            // Remove prefabs that are already in the list of batch prefab baker's prefabs.
            {
                List <GameObject> tmpNewPrefabs = new List <GameObject>();
                for (int i = 0; i < newPrefabs.Count; i++)
                {
                    bool found = false;
                    for (int j = 0; j < prefabBaker.prefabRows.Length; j++)
                    {
                        if (prefabBaker.prefabRows[j].sourcePrefab == newPrefabs[i])
                        {
                            found = true;
                            break;
                        }
                    }

                    if (!found)
                    {
                        tmpNewPrefabs.Add(newPrefabs[i]);
                    }
                }

                newPrefabs = tmpNewPrefabs;
            }

            if (MB3_MeshCombiner.EVAL_VERSION)
            {
                int numPrefabsLimit = MB_BatchPrefabBakerEditorFunctions.EvalVersionPrefabLimit;
                int numNew          = numPrefabsLimit - prefabBaker.prefabRows.Length;
                if (newPrefabs.Count + prefabBaker.prefabRows.Length > numPrefabsLimit)
                {
                    Debug.LogError("The free version of Mesh Baker is limited to batch baking " + numPrefabsLimit +
                                   " prefabs. The full version has no limit on the number of prefabs that can be baked. " + (newPrefabs.Count - numNew) + " prefabs were not added.");
                }


                for (int i = newPrefabs.Count - 1; i >= numNew; i--)
                {
                    newPrefabs.RemoveAt(i);
                }
            }

            List <MB3_BatchPrefabBaker.MB3_PrefabBakerRow> newRows = new List <MB3_BatchPrefabBaker.MB3_PrefabBakerRow>();

            if (prefabBaker.prefabRows == null)
            {
                prefabBaker.prefabRows = new MB3_BatchPrefabBaker.MB3_PrefabBakerRow[0];
            }
            newRows.AddRange(prefabBaker.prefabRows);
            for (int i = 0; i < newPrefabs.Count; i++)
            {
                MB3_BatchPrefabBaker.MB3_PrefabBakerRow row = new MB3_BatchPrefabBaker.MB3_PrefabBakerRow();
                row.sourcePrefab = newPrefabs[i];
                newRows.Add(row);
            }


            Undo.RecordObject(prefabBaker, "Populate prefab rows");
            prefabBaker.prefabRows = newRows.ToArray();
        }
Ejemplo n.º 4
0
        public static void PopulatePrefabRowsFromTextureBaker(MB3_BatchPrefabBaker prefabBaker)
        {
            MB3_TextureBaker  texBaker   = prefabBaker.GetComponent <MB3_TextureBaker>();
            List <GameObject> newPrefabs = 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 (!newPrefabs.Contains((GameObject)obj))
                    {
                        newPrefabs.Add((GameObject)obj);
                    }
                }
                else
                {
                    Debug.LogWarning(String.Format("Object {0} did not have a prefab", gos[i]));
                }
            }

            // Remove prefabs that are already in the list of batch prefab baker's prefabs.
            {
                List <GameObject> tmpNewPrefabs = new List <GameObject>();
                for (int i = 0; i < newPrefabs.Count; i++)
                {
                    bool found = false;
                    for (int j = 0; j < prefabBaker.prefabRows.Length; j++)
                    {
                        if (prefabBaker.prefabRows[j].sourcePrefab == newPrefabs[i])
                        {
                            found = true;
                            break;
                        }
                    }

                    if (!found)
                    {
                        tmpNewPrefabs.Add(newPrefabs[i]);
                    }
                }

                newPrefabs = tmpNewPrefabs;
            }

            List <MB3_BatchPrefabBaker.MB3_PrefabBakerRow> newRows = new List <MB3_BatchPrefabBaker.MB3_PrefabBakerRow>();

            if (prefabBaker.prefabRows == null)
            {
                prefabBaker.prefabRows = new MB3_BatchPrefabBaker.MB3_PrefabBakerRow[0];
            }
            newRows.AddRange(prefabBaker.prefabRows);
            for (int i = 0; i < newPrefabs.Count; i++)
            {
                MB3_BatchPrefabBaker.MB3_PrefabBakerRow row = new MB3_BatchPrefabBaker.MB3_PrefabBakerRow();
                row.sourcePrefab = newPrefabs[i];
                newRows.Add(row);
            }


            Undo.RecordObject(prefabBaker, "Populate prefab rows");
            prefabBaker.prefabRows = newRows.ToArray();
        }