Beispiel #1
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;
            Event      e = Event.current;

            //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();

            if (!placing && e.type == EventType.keyDown && e.keyCode == KeyCode.Backspace)
            {
                e.Use();
                Undo.RegisterCompleteObjectUndo(script, "Delete Vertex");
                Undo.RecordObject(script.GetComponent <MeshFilter>().sharedMesh, "Delete Vertex");
                DeleteSelected();
                return;
            }

            //in the edit mode, ray hit something
            if (placing)
            {
                Tools.current = Tool.None;
                Handles.BeginGUI();
                GUILayout.Window(2, new Rect(Screen.width - 157, Screen.height - 100, 100, 50), (id) =>
                {
                    GUILayout.Label(editOnText);
                }, "Control Info Box");
                Handles.EndGUI();

                if (Physics.Raycast(worldRay, out hitInfo))
                {
                    //the actual hit position
                    mousePosition = hitInfo.point;

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

                        //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, "Add Vertex");
                        }

                        //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
                        e.Use();

                        //add point to existing vertex, if near any
                        //but don't add it to the same submesh (closed mesh)
                        //otherwise just add a new vertex position
                        if (script.current.Contains(dragIndex))
                        {
                            script.AddPoint(script.transform.TransformPoint(script.list[dragIndex]));
                        }
                        else if (dragIndex >= 0)
                        {
                            script.AddPoint(dragIndex);
                        }
                        else
                        {
                            script.AddPoint(mousePosition);
                        }

                        //invoke new mesh calculation
                        Undo.RegisterCompleteObjectUndo(script.subMesh, "Add Vertex");
                        script.CreateMesh();
                        return;
                    }
                }
            }

            //not in edit mode
            if (!placing)
            {
                Handles.BeginGUI();
                GUILayout.Window(2, new Rect(Screen.width - 200, Screen.height - 100, 100, 50), (id) =>
                {
                    GUILayout.Label(editOffText);
                }, "Control Info Box");
                Handles.EndGUI();

                //clicking near vertices will select them and show handles
                if (e.type == EventType.mouseUp && e.button == 0 && !e.alt)
                {
                    //select/unselect vertex point
                    if (dragIndex >= 0)
                    {
                        if (!selected.Contains(dragIndex))
                        {
                            selected.Add(dragIndex);
                        }
                        else
                        {
                            selected.Remove(dragIndex);
                        }

                        SceneView.RepaintAll();
                    }
                    else if (selected.Count == 0)
                    {
                        Selection.activeObject = null;
                    }
                }
                //unselect all vertices
                else if (e.type == EventType.mouseUp && e.button == 1 && !e.alt)
                {
                    selected.Clear();
                }
            }

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

            //handle undo of vertex modifications (redraw mesh)
            if (e.type == EventType.ValidateCommand && e.commandName == "UndoRedoPerformed")
            {
                undoRedo = true;
            }

            HandleUtility.AddDefaultControl(-1);
            HandleUtility.Repaint();
        }
        /// <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);

            if (GUILayout.Button("Triangulate"))
            {
                script.RegenerateMesh(ConvertAllPoints());
            }

            //enter placement mode
            if (!placing && GUILayout.Button("Edit Mode: Off"))
            {
                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("Edit Mode: On"))
            {
                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("Save as Prefab"))
            {
                //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);
                }

                //create the mesh asset at the path specified, with unique name
                AssetDatabase.CreateAsset(mesh, assetPath + 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;
            }
        }