bool SaveMeshAssetsRecursive(GameObject root, GameObject gameObject, string strFile, bool bRecurseIntoChildren, bool bAssetAlreadyCreated, ref int nProgressElementsCounter)
    {
        if (gameObject == null || Simplifier.Cancelled)
        {
            return(bAssetAlreadyCreated);
        }

        MeshSimplify meshSimplify = gameObject.GetComponent <MeshSimplify>();

        if (meshSimplify != null && meshSimplify.HasData() && (meshSimplify.m_meshSimplifyRoot == null || meshSimplify.m_meshSimplifyRoot.gameObject == root))
        {
            int nTotalProgressElements = meshSimplify.m_meshSimplifyRoot != null ? (meshSimplify.m_meshSimplifyRoot.m_listDependentChildren.Count + 1) : 1;

            if (meshSimplify.m_simplifiedMesh != null && MeshSimplify.HasValidMeshData(meshSimplify.gameObject))
            {
                float fT = (float)nProgressElementsCounter / (float)nTotalProgressElements;
                Progress("Saving meshes to asset file", meshSimplify.name, fT);

                if (Simplifier.Cancelled)
                {
                    return(bAssetAlreadyCreated);
                }

                if (bAssetAlreadyCreated == false && UnityEditor.AssetDatabase.Contains(meshSimplify.m_simplifiedMesh) == false)
                {
                    //Debug.Log("Creating asset " + meshSimplify.m_simplifiedMesh.name);

                    UnityEditor.AssetDatabase.CreateAsset(meshSimplify.m_simplifiedMesh, strFile);
                    bAssetAlreadyCreated = true;
                }
                else
                {
                    if (UnityEditor.AssetDatabase.Contains(meshSimplify.m_simplifiedMesh) == false)
                    {
                        //Debug.Log("Adding asset " + meshSimplify.m_simplifiedMesh.name);

                        UnityEditor.AssetDatabase.AddObjectToAsset(meshSimplify.m_simplifiedMesh, strFile);
                        UnityEditor.AssetDatabase.ImportAsset(UnityEditor.AssetDatabase.GetAssetPath(meshSimplify.m_simplifiedMesh));
                    }
                }

                nProgressElementsCounter++;
            }
        }

        if (bRecurseIntoChildren)
        {
            for (int nChild = 0; nChild < gameObject.transform.childCount; nChild++)
            {
                bAssetAlreadyCreated = SaveMeshAssetsRecursive(root, gameObject.transform.GetChild(nChild).gameObject, strFile, bRecurseIntoChildren, bAssetAlreadyCreated, ref nProgressElementsCounter);
            }
        }

        return(bAssetAlreadyCreated);
    }
示例#2
0
    private void AddMaterials(GameObject theGameObject, Dictionary <GameObject, Material[]> dicMaterials)
    {
        Renderer theRenderer = theGameObject.GetComponent <Renderer>();

        if (theRenderer != null && theRenderer.sharedMaterials != null && (MeshSimplify.HasValidMeshData(theGameObject) || theGameObject.GetComponent <MeshSimplify>() != null))
        {
            dicMaterials.Add(theGameObject, theRenderer.sharedMaterials);
        }

        if (m_selectedMeshSimplify.RecurseIntoChildren)
        {
            for (int i = 0; i < theGameObject.transform.childCount; i++)
            {
                AddMaterials(theGameObject.transform.GetChild(i).gameObject, dicMaterials);
            }
        }
    }
示例#3
0
    private IEnumerator ComputeMeshWithVertices(float fAmount)
    {
        Simplifier.CoroutineFrameMiliseconds = 20;

        foreach (KeyValuePair <GameObject, Material[]> pair in m_objectMaterials)
        {
            MeshSimplify        meshSimplify = pair.Key.GetComponent <MeshSimplify>();
            MeshFilter          meshFilter   = pair.Key.GetComponent <MeshFilter>();
            SkinnedMeshRenderer skin         = pair.Key.GetComponent <SkinnedMeshRenderer>();

            if (meshSimplify == null)
            {
                meshSimplify = pair.Key.AddComponent <MeshSimplify>();
                meshSimplify.m_meshSimplifyRoot = m_selectedMeshSimplify;
                m_selectedMeshSimplify.m_listDependentChildren.Add(meshSimplify);
            }

            if (meshSimplify.MeshSimplifier == null)
            {
                meshSimplify.MeshSimplifier           = meshSimplify.gameObject.AddComponent <Simplifier>();
                meshSimplify.MeshSimplifier.hideFlags = HideFlags.HideInInspector;
                meshSimplify.ConfigureSimplifier();
            }

            if (meshSimplify && MeshSimplify.HasValidMeshData(pair.Key))
            {
                Mesh newMesh = null;

                if (meshFilter != null)
                {
                    newMesh = Mesh.Instantiate(meshFilter.sharedMesh);
                }
                else if (skin != null)
                {
                    newMesh = Mesh.Instantiate(skin.sharedMesh);
                }

                if (meshSimplify.HasData() == false)
                {
                    meshSimplify.GetMeshSimplifier().CoroutineEnded = false;

                    StartCoroutine(meshSimplify.GetMeshSimplifier().ProgressiveMesh(pair.Key, meshFilter != null ? meshFilter.sharedMesh : skin.sharedMesh, null, meshSimplify.name, Progress));

                    while (meshSimplify.GetMeshSimplifier().CoroutineEnded == false)
                    {
                        yield return(null);
                    }
                }

                if (meshSimplify.GetMeshSimplifier() != null)
                {
                    meshSimplify.GetMeshSimplifier().CoroutineEnded = false;

                    StartCoroutine(meshSimplify.GetMeshSimplifier().ComputeMeshWithVertexCount(pair.Key, newMesh, Mathf.RoundToInt(fAmount * meshSimplify.GetMeshSimplifier().GetOriginalMeshUniqueVertexCount()), meshSimplify.name, Progress));

                    while (meshSimplify.GetMeshSimplifier().CoroutineEnded == false)
                    {
                        yield return(null);
                    }

                    if (meshFilter != null)
                    {
                        meshFilter.mesh = newMesh;
                    }
                    else if (skin != null)
                    {
                        skin.sharedMesh = newMesh;
                    }

                    meshSimplify.m_simplifiedMesh = newMesh;
                }
            }
        }

        m_bFinished = true;
    }
    public override void OnInspectorGUI()
    {
        MeshSimplify meshSimplify;

        string strIncludeChildrenLabel = "Recurse Into Children";
        int    nButtonWidth            = 200;
        int    nButtonWidthSmall       = 130;

        foreach (Object targetObject in targets)
        {
            meshSimplify = targetObject as MeshSimplify;

            if (meshSimplify.m_meshSimplifyRoot != null && targets.Length > 1)
            {
                EditorGUILayout.HelpBox("One or more GameObjects of the selection is not a root MeshSimplify GameObject. Only root MeshSimplify GameObjects can be edited at the same time.", MessageType.Warning);
                return;
            }
        }

        if (targets.Length > 1)
        {
            EditorGUILayout.HelpBox("Multiple selection", MessageType.Info);
        }

        serializedObject.Update();

        EditorGUILayout.Space();

        meshSimplify = target as MeshSimplify;

        if (meshSimplify.m_meshSimplifyRoot == null)
        {
            EditorGUILayout.PropertyField(PropertyGenerateIncludeChildren, new GUIContent(strIncludeChildrenLabel, "If checked, we will traverse the whole GameObject's hierarchy looking for meshes"));

            EditorGUI.BeginChangeCheck();
            EditorGUILayout.PropertyField(PropertyEnablePrefabUsage, new GUIContent("Enable Prefab Usage", "Will save the generated mesh assets to disk, so that this GameObject can be used as a prefab and be instantiated at runtime. Otherwise the mesh won't be available"));

            if (EditorGUI.EndChangeCheck())
            {
                if (PropertyEnablePrefabUsage.boolValue)
                {
                    m_bEnablePrefabUsage = true;
                }
                else
                {
                    m_bDisablePrefabUsage = true;
                }
            }
        }
        else
        {
            if (PropertyExcludedFromTree.boolValue)
            {
                GUILayout.Label("Object has been excluded from mesh simplification.");
            }
            else
            {
                GUILayout.Label("Child MeshSimplify GameObject depending on " + meshSimplify.m_meshSimplifyRoot.name);
                EditorGUILayout.PropertyField(PropertyOverrideRootSettings, new GUIContent("Override " + meshSimplify.m_meshSimplifyRoot.name + " settings", "Will allow to edit this object's own parameters, instead of inheriting those of the root Automatic LOD GameObject"));
            }
        }

        if (meshSimplify.m_meshSimplifyRoot == null || (PropertyOverrideRootSettings.boolValue == true && PropertyExcludedFromTree.boolValue == false))
        {
            bool bIsOverriden = PropertyOverrideRootSettings.boolValue == true;

            EditorGUI.BeginChangeCheck();
            EditorGUILayout.PropertyField(PropertyUseEdgeLength, new GUIContent("Use Edge Length", "Will take edge length into consideration when simplifying the mesh. Edges with higher length will be more likely to be kept"));
            if (EditorGUI.EndChangeCheck())
            {
                PropertyDataDirty.boolValue = true;
            }

            EditorGUI.BeginChangeCheck();
            EditorGUILayout.PropertyField(PropertyUseCurvature, new GUIContent("Use Curvature", "Will take the angle between triangles into consideration. Edges with smaller angles between two triangles will be more likely to be kept when simplifying the mesh."));
            if (EditorGUI.EndChangeCheck())
            {
                PropertyDataDirty.boolValue = true;
            }

            EditorGUI.BeginChangeCheck();
            EditorGUILayout.PropertyField(PropertyProtectTexture, new GUIContent("Protect Texture", "Will try to keep mapping integrity during the process of mesh simplification"));
            if (EditorGUI.EndChangeCheck())
            {
                PropertyDataDirty.boolValue = true;
            }

            EditorGUI.BeginChangeCheck();
            EditorGUILayout.PropertyField(PropertyLockBorder, new GUIContent("Keep Borders", "Will try to keep those vertices that form an object's border"));
            if (EditorGUI.EndChangeCheck())
            {
                PropertyDataDirty.boolValue = true;
            }

            EditorGUILayout.Space();

            float fVertexAmount = EditorGUILayout.Slider(new GUIContent("Vertex %", "The percentage of vertices from the original mesh to keep when simplifying it"), PropertyVertexAmount.floatValue * 100.0f, 0.0f, 100.0f);
            PropertyVertexAmount.floatValue = Mathf.Clamp01(fVertexAmount / 100.0f);
            int nSimplifiedMeshVertexCount = meshSimplify.GetSimplifiedVertexCount(bIsOverriden == false);
            int nMeshVertexCount           = meshSimplify.GetOriginalVertexCount(bIsOverriden == false);

            EditorGUILayout.LabelField("Vertex count: " + nSimplifiedMeshVertexCount + "/" + nMeshVertexCount);

            int nSimplifiedMeshTriangleCount = meshSimplify.GetSimplifiedTriangleCount(bIsOverriden == false);
            int nMeshTriangleCount           = meshSimplify.GetOriginalTriangleCount(bIsOverriden == false);

            EditorGUILayout.LabelField("Triangle count: " + nSimplifiedMeshTriangleCount + "/" + nMeshTriangleCount);

            //EditorGUILayout.LabelField("Child nodes: " + (meshSimplify.m_listDependentChildren == null ? 0 : meshSimplify.m_listDependentChildren.Count));

            EditorGUILayout.Space();

            EditorGUI.BeginChangeCheck();

            m_bPreviewOriginalMesh = EditorGUILayout.Toggle(new GUIContent("Preview Original Mesh", "Allows to quickly switch between viewing the simplified mesh and the original mesh to check the reduction quality"), m_bPreviewOriginalMesh);

            if (EditorGUI.EndChangeCheck())
            {
                if (m_bPreviewOriginalMesh)
                {
                    meshSimplify.RestoreOriginalMesh(false, bIsOverriden == false);
                }
                else
                {
                    meshSimplify.AssignSimplifiedMesh(bIsOverriden == false);
                }
            }

            EditorGUILayout.Space();
        }

        if (meshSimplify.m_meshSimplifyRoot == null)
        {
            PropertyExpandRelevanceSpheres.boolValue = EditorGUILayout.Foldout(PropertyExpandRelevanceSpheres.boolValue, new GUIContent("Vertex Relevance Modifiers:"));

            if (PropertyExpandRelevanceSpheres.boolValue)
            {
                EditorGUILayout.HelpBox("Use vertex relevance spheres to select which vertices should be preserved with more or less priority when simplifying the mesh.", MessageType.Info);

                EditorGUILayout.Space();

                GUILayout.BeginHorizontal();
                GUILayout.FlexibleSpace();

                if (GUILayout.Button(new GUIContent("Add New Sphere", "Adds a new vertex relevance sphere"), GUILayout.Width(nButtonWidthSmall)))
                {
                    PropertyRelevanceSpheres.InsertArrayElementAtIndex(0);
                    PropertyDataDirty.boolValue = true;
                    m_bSetupNewRelevanceSphere  = true;
                }

                GUILayout.FlexibleSpace();
                GUILayout.EndHorizontal();

                EditorGUILayout.Space();

                EditorGUI.indentLevel++;

                int nSphereToDelete = -1;

                for (int i = 0; i < PropertyRelevanceSpheres.arraySize; i++)
                {
                    SerializedProperty elementProperty = PropertyRelevanceSpheres.GetArrayElementAtIndex(i);

                    SerializedProperty elementExpanded  = elementProperty.FindPropertyRelative("m_bExpanded");
                    SerializedProperty elementPosition  = elementProperty.FindPropertyRelative("m_v3Position");
                    SerializedProperty elementRotation  = elementProperty.FindPropertyRelative("m_v3Rotation");
                    SerializedProperty elementScale     = elementProperty.FindPropertyRelative("m_v3Scale");
                    SerializedProperty elementRelevance = elementProperty.FindPropertyRelative("m_fRelevance");

                    elementExpanded.boolValue = EditorGUILayout.Foldout(elementExpanded.boolValue, new GUIContent("Sphere"));

                    if (elementExpanded.boolValue)
                    {
                        bool bWideMode = EditorGUIUtility.wideMode;

                        EditorGUIUtility.wideMode = true;

                        EditorGUI.BeginChangeCheck();
                        EditorGUILayout.PropertyField(elementPosition, new GUIContent("Position"));
                        if (EditorGUI.EndChangeCheck())
                        {
                            PropertyDataDirty.boolValue = true;
                        }

                        EditorGUI.BeginChangeCheck();
                        EditorGUILayout.PropertyField(elementRotation, new GUIContent("Rotation"));
                        if (EditorGUI.EndChangeCheck())
                        {
                            PropertyDataDirty.boolValue = true;
                        }

                        EditorGUI.BeginChangeCheck();
                        EditorGUILayout.PropertyField(elementScale, new GUIContent("Scale"));
                        if (EditorGUI.EndChangeCheck())
                        {
                            PropertyDataDirty.boolValue = true;
                        }

                        EditorGUI.BeginChangeCheck();
                        elementRelevance.floatValue = EditorGUILayout.Slider(new GUIContent("Relevance", "Tells the simplification algorithm how relevant the vertices inside this sphere are. Default relevance is 0, use lower values to discard non important vertices, and higher values to keep them before others when simplifying the mesh"), elementRelevance.floatValue, -1.0f, 1.0f);
                        if (EditorGUI.EndChangeCheck())
                        {
                            PropertyDataDirty.boolValue = true;
                        }

                        GUILayout.BeginHorizontal();
                        GUILayout.FlexibleSpace();

                        if (GUILayout.Button(new GUIContent("Remove Sphere", "Removes this simplification sphere"), GUILayout.Width(nButtonWidthSmall)))
                        {
                            nSphereToDelete             = i;
                            PropertyDataDirty.boolValue = true;
                        }

                        GUILayout.FlexibleSpace();
                        GUILayout.EndHorizontal();

                        EditorGUIUtility.wideMode = bWideMode;
                    }
                }

                if (nSphereToDelete >= 0)
                {
                    PropertyRelevanceSpheres.DeleteArrayElementAtIndex(nSphereToDelete);
                }

                EditorGUI.indentLevel--;
            }

            EditorGUILayout.Space();
        }

        if (meshSimplify.m_meshSimplifyRoot == null || (PropertyOverrideRootSettings.boolValue == true && PropertyExcludedFromTree.boolValue == false))
        {
            GUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();

            if (GUILayout.Button(new GUIContent("Compute mesh", "Starts the mesh simplification process and assigns the GameObject the new simplified mesh"), GUILayout.Width(nButtonWidth)))
            {
                m_bComputeMesh = true;
            }

            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();

            if (GUILayout.Button(new GUIContent("Restore Original Mesh...", "Deletes the simplified data and restores the original mesh"), GUILayout.Width(nButtonWidth)))
            {
                if (EditorUtility.DisplayDialog("Delete all data and restore original mesh?", "Are you sure you want to delete all data and restore the original mesh?", "Delete", "Cancel"))
                {
                    m_bDeleteData = true;
                }
            }

            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal();
        }

        if (meshSimplify.m_meshSimplifyRoot != null && PropertyExcludedFromTree.boolValue == false)
        {
            EditorGUILayout.Space();

            GUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();

            if (GUILayout.Button(new GUIContent("Exclude from tree...", "Restores this GameObject's original mesh and excludes it from the mesh simplification tree"), GUILayout.Width(nButtonWidth)))
            {
                if (EditorUtility.DisplayDialog("Remove from tree?", "Are you sure you want to restore this gameobject's mesh and exclude it from the tree?", "Remove", "Cancel"))
                {
                    m_bRemoveFromTree = true;
                }
            }

            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal();
        }

        serializedObject.ApplyModifiedProperties();

        bool bRepaint = false;

        if (m_bEnablePrefabUsage)
        {
            m_bEnablePrefabUsage = false;
            SaveMeshAssets();
        }

        if (m_bDisablePrefabUsage)
        {
            m_bDisablePrefabUsage = false;

            if (PropertyEnablePrefabUsage.boolValue == false)
            {
                foreach (Object targetObject in targets)
                {
                    meshSimplify = targetObject as MeshSimplify;
                    meshSimplify.DisablePrefabUsage(true);
                }
            }
        }

        if (m_bComputeMesh && Event.current.type == EventType.Repaint)
        {
            m_bComputeMesh = false;

            Simplifier.Cancelled = false;

            foreach (Object targetObject in targets)
            {
                meshSimplify = targetObject as MeshSimplify;

                if (meshSimplify.HasData() == false)
                {
                    if (PropertyGenerateIncludeChildren.boolValue == false)
                    {
                        if (MeshSimplify.HasValidMeshData(meshSimplify.gameObject) == false)
                        {
                            EditorUtility.DisplayDialog("Error", "Object " + meshSimplify.name + " has no MeshFilter nor Skinned Mesh to process. Please use the \"" + strIncludeChildrenLabel + "\" parameter if you want to process the whole " + meshSimplify.name + " hierarchy for meshes", "OK");
                            continue;
                        }
                    }
                }

                try
                {
                    if (meshSimplify.HasDataDirty() || meshSimplify.HasData() == false || meshSimplify.HasNonMeshSimplifyGameObjectsInTree())
                    {
                        meshSimplify.RestoreOriginalMesh(true, meshSimplify.m_meshSimplifyRoot == null);
                        meshSimplify.ComputeData(meshSimplify.m_meshSimplifyRoot == null, Progress);

                        if (Simplifier.Cancelled)
                        {
                            meshSimplify.RestoreOriginalMesh(true, meshSimplify.m_meshSimplifyRoot == null);
                            break;
                        }
                    }

                    meshSimplify.ComputeMesh(meshSimplify.m_meshSimplifyRoot == null, Progress);

                    if (Simplifier.Cancelled)
                    {
                        break;
                    }

                    meshSimplify.AssignSimplifiedMesh(meshSimplify.m_meshSimplifyRoot == null);

                    if (meshSimplify.m_strAssetPath != null && meshSimplify.m_bEnablePrefabUsage)
                    {
                        SaveMeshAssets();
                    }
                }
                catch (System.Exception e)
                {
                    Debug.LogError("Error generating mesh: " + e.Message + " Stack: " + e.StackTrace);
                    EditorUtility.ClearProgressBar();
                    Simplifier.Cancelled = false;
                }

                Simplifier.Cancelled = false;
            }

            bRepaint = true;
            EditorUtility.ClearProgressBar();
        }

        if (m_bDeleteData && Event.current.type == EventType.Repaint)
        {
            m_bDeleteData = false;

            foreach (Object targetObject in targets)
            {
                meshSimplify = targetObject as MeshSimplify;
                meshSimplify.RestoreOriginalMesh(true, meshSimplify.m_meshSimplifyRoot == null);
                RemoveChildMeshSimplifyComponents(meshSimplify);
            }

            bRepaint = true;
        }

        if (m_bRemoveFromTree && Event.current.type == EventType.Repaint)
        {
            m_bRemoveFromTree = false;
            meshSimplify      = target as MeshSimplify;
            meshSimplify.RemoveFromTree();

            if (Application.isEditor && Application.isPlaying == false)
            {
                UnityEngine.Object.DestroyImmediate(meshSimplify);
            }
            else
            {
                UnityEngine.Object.Destroy(meshSimplify);
            }

            bRepaint = true;
        }

        if (m_bSetupNewRelevanceSphere)
        {
            m_bSetupNewRelevanceSphere = false;

            foreach (Object targetObject in targets)
            {
                meshSimplify = targetObject as MeshSimplify;

                if (meshSimplify.m_aRelevanceSpheres != null && meshSimplify.m_aRelevanceSpheres.Length > 0)
                {
                    meshSimplify.m_aRelevanceSpheres[0].SetDefault(meshSimplify.transform, 0.0f);
                }
            }
        }

        if (bRepaint)
        {
            Repaint();
        }
    }