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