private void PerformUndoRedo()
        {
            undoRedo = false;
            if (script.current.Count > 1 && script.subMesh)
            {
                script.subMesh.triangles = script.RecalculateTriangles(null);
                OptimizeMesh(script.subMesh);
                return;
            }

            Mesh sharedMesh = script.GetComponent <MeshFilter>().sharedMesh;

            if (!sharedMesh)
            {
                return;
            }

            List <int> triangles = new List <int>();

            for (int i = 0; i < script.subPoints.Count; i++)
            {
                triangles.AddRange(script.RecalculateTriangles(script.subPoints[i].list));
            }

            sharedMesh.triangles = new int[sharedMesh.vertexCount * 3];
            script.UpdateMesh(ConvertAllPoints());
            sharedMesh.triangles = triangles.ToArray();
            if (!placing)
            {
                script.Combine();
            }
        }
Exemple #2
0
        /// <summary>
        /// Custom inspector override for buttons.
        /// </summary>
        public override void OnInspectorGUI()
        {
            DrawDefaultInspector();
            EditorGUILayout.Space();

            //display current count of placed vertices in the active submesh
            EditorGUILayout.LabelField("Current Vertices: " + script.current.Count);

            //enter placement mode
            if (!placing && GUILayout.Button("编辑模式:关闭"))
            {
                Undo.RegisterCompleteObjectUndo(script, "Edit On");

                //if possible, create new submesh
                if (CheckSubMesh())
                {
                    GameObject newObj = script.CreateSubMesh();
                    Undo.RegisterCreatedObjectUndo(newObj, "Edit On");
                }

                //clear handle selections
                selected.Clear();
                placing = true;
            }

            GUI.color = Color.yellow;

            //leave placement mode and try to combine submeshes
            if (placing && GUILayout.Button("编辑模式:开启"))
            {
                Undo.RegisterCompleteObjectUndo(script, "Edit Off");

                //if possible, combine submeshes
                if (CheckCombine())
                {
                    //get all mesh filters
                    MeshFilter[] meshFilters = script.GetComponentsInChildren <MeshFilter>();
                    Undo.RecordObject(meshFilters[0], "Edit Off");

                    //let the script combine them
                    script.Combine();

                    for (int i = 1; i < meshFilters.Length; i++)
                    {
                        Undo.DestroyObjectImmediate(meshFilters[i].gameObject);
                    }
                }

                placing = false;
            }

            GUI.color = Color.white;

            //export mesh to asset and prefab
            if (GUILayout.Button("[此步不用操作]保存网格预设(不建议保存|保存场景即可)"))
            {
                //get gameobject and its mesh filter
                GameObject gObj = script.gameObject;
                Mesh       mesh = gObj.GetComponent <MeshFilter>().sharedMesh;

                if (!mesh)
                {
                    Debug.LogWarning("Could not save as prefab, asset does not have a Mesh.");
                    return;
                }

                if (AssetDatabase.Contains(mesh))
                {
                    Debug.Log("Mesh asset already exists. Cancelling.");
                    return;
                }

                //get the current unix timestamp for a unique naming scheme
                var    epochStart = new System.DateTime(1970, 1, 1, 0, 0, 0, System.DateTimeKind.Utc);
                string timestamp  = (System.DateTime.UtcNow - epochStart).TotalSeconds.ToString("F0");
                string assetName  = "NavMesh_";

                //check that the folder does exist
                string dir = Path.GetDirectoryName(assetPath);
                if (!Directory.Exists(dir))
                {
                    Directory.CreateDirectory(dir);
                    AssetDatabase.ImportAsset(dir);
                }

#if UNITY_5_3_OR_NEWER
                string sceneName = UnityEngine.SceneManagement.SceneManager.GetActiveScene().name;
#else
                string sceneName = Application.loadedLevelName;
#endif

                //create the mesh asset at the path specified, with unique name
                AssetDatabase.CreateAsset(mesh, assetPath + sceneName + "/" + assetName + timestamp + ".asset");
                AssetDatabase.SaveAssets();

                //create the prefab of this gameobject at the path specified, with the same name
                PrefabUtility.CreatePrefab(assetPath + assetName + timestamp + ".prefab", gObj,
                                           ReplacePrefabOptions.ConnectToPrefab);
                //rename instance to prefab name
                gObj.name = assetName + timestamp;
            }

            if (placing)
            {
                EditorGUILayout.Separator();
                EditorGUILayout.LabelField("Hint:", EditorStyles.boldLabel);
                EditorGUILayout.TextArea("Click on colliders to place vertices.\n" +
                                         "CTRL + click to start a new submesh.");
            }

            //================================================
            if (GUILayout.Button("将选中瞄点同步高度(以第一个选中的高度为准)"))
            {
                //don't continue without selected vertices
                if (selected.Count == 0)
                {
                    return;
                }

                Undo.RegisterCompleteObjectUndo(script, "Handle Moved");
                Mesh myMesh = script.gameObject.GetComponent <MeshFilter>().sharedMesh;
                if (myMesh)
                {
                    Undo.RecordObject(myMesh, "Handle Moved");
                }

                float standPosY = script.list[selected[0]].y;
                for (int i = 0; i < selected.Count; i++)
                {
                    Vector3 curPos = script.list[selected[i]];
                    script.list[selected[i]] = new Vector3(curPos.x, standPosY, curPos.z);
                }
                script.UpdateMesh(ConvertAllPoints());

                Debug.Log("将选中瞄点同步高度(以第一个选中的高度为准)==>" + standPosY);
            }
        }
        /// <summary>
        /// Draw Scene GUI handles, circles and outlines for submesh vertices.
        /// <summary>
        public void OnSceneGUI()
        {
            //get world positions of vertices
            allPoints = ConvertAllPoints();

            //create a ray to get where we clicked in the scene view and pass in mouse position
            Ray        worldRay = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);
            RaycastHit hitInfo;

            //this prevents selecting other objects in the scene
            int controlID = GUIUtility.GetControlID(FocusType.Passive);

            HandleUtility.AddDefaultControl(controlID);
            //find index of closest vertex, if any
            dragIndex = FindClosest();

            //in the edit mode, ray hit something
            if (placing && Physics.Raycast(worldRay, out hitInfo))
            {
                //the actual hit position
                mousePosition = hitInfo.point;
                Event e = Event.current;

                //place new point if the left mouse button was clicked
                if (e.type == EventType.mouseUp && e.button == 0)
                {
                    Undo.RegisterCompleteObjectUndo(script, "Split Mesh");

                    //get current submesh vertex count
                    int currentCount = script.current.Count;
                    //create a new submesh, if control was hold in addition to the mouse click
                    //or if autoSplit is true and the current count exceeds splitAt
                    if ((e.control && currentCount >= 3) ||
                        (script.autoSplit && currentCount >= script.splitAt))
                    {
                        GameObject newObj = script.CreateSubMesh();
                        Undo.RegisterCreatedObjectUndo(newObj, "Split Mesh");
                    }

                    //call this method when you've used an event.
                    //the event's type will be set to EventType.Used,
                    //causing other GUI elements to ignore it
                    Event.current.Use();

                    //add point to existing vertex, if near any
                    //otherwise just add a new vertex position
                    if (dragIndex >= 0)
                    {
                        script.AddPoint(dragIndex);
                    }
                    else
                    {
                        script.AddPoint(mousePosition);
                    }

                    //invoke new mesh calculation
                    Undo.RecordObject(script.subMesh, "Split Mesh");
                    script.CreateMesh();
                    return;
                }
            }

            //not in edit mode, clicking near vertices will select them and show handles
            if (!placing && Event.current.type == EventType.mouseUp && Event.current.button == 0)
            {
                //select/unselect vertex point
                if (dragIndex >= 0)
                {
                    if (!selected.Contains(dragIndex))
                    {
                        selected.Add(dragIndex);
                    }
                    else
                    {
                        selected.Remove(dragIndex);
                    }

                    SceneView.RepaintAll();
                }
            }

            //right-clicking anywhere will unselect all vertices
            if (!placing && Event.current.type == EventType.mouseUp && Event.current.button == 1)
            {
                selected.Clear();
            }

            //draw scene gizmos
            DrawSelectedHandles();
            DrawPolygonOutline();

            //handle undo of vertex modifications (redraw mesh)
            if (Event.current.commandName == "UndoRedoPerformed")
            {
                if (!script.GetComponent <MeshFilter>().sharedMesh)
                {
                    return;
                }

                script.UpdateMesh(ConvertAllPoints());
                return;
            }
        }