//called whenever the inspector gui gets rendered public override void OnInspectorGUI() { //don't draw inspector fields if the path contains less than 2 points //(a path with less than 2 points really isn't a path) if (m_WaypointsCount.intValue < 2) { return; } //this pulls the relative variables from unity runtime and stores them in the object m_Object.Update(); //create new checkboxes for path gizmo property m_Check1.boolValue = EditorGUILayout.Toggle("Walkable", m_Check1.boolValue); m_Check2.boolValue = EditorGUILayout.Toggle("Closure", m_Check2.boolValue); //create new property fields for editing waypoint gizmo colors EditorGUILayout.PropertyField(m_Color1); EditorGUILayout.PropertyField(m_Color2); //get waypoint array var waypoints = GetWaypointArray(); //force naming scheme RenameWaypoints(); //calculate path length of all waypoints Vector3[] wpPositions = new Vector3[waypoints.Length]; for (int i = 0; i < waypoints.Length; i++) { wpPositions[i] = waypoints[i].position; } float pathLength = WaypointManager.GetPathLength(wpPositions); //path length label, show calculated path length GUILayout.Label("Path Length: " + pathLength); //waypoint index header GUILayout.Label("Waypoints: ", EditorStyles.boldLabel); //loop through the waypoint array for (int i = 0; i < waypoints.Length; i++) { GUILayout.BeginHorizontal(); //indicate each array slot with index number in front of it GUILayout.Label(i + ".", GUILayout.Width(20)); //create an object field for every waypoint EditorGUILayout.ObjectField(waypoints[i], typeof(Transform), true); //display an "Add Waypoint" button for every array row except the last one if (i < waypoints.Length && GUILayout.Button("+", GUILayout.Width(30f))) { AddWaypointAtIndex(i); break; } //display an "Remove Waypoint" button for every array row except the first and last one if (i > 0 && i < waypoints.Length - 1 && GUILayout.Button("-", GUILayout.Width(30f))) { RemoveWaypointAtIndex(i); break; } GUILayout.EndHorizontal(); } EditorGUILayout.Space(); //button to move all waypoints down to the ground if (GUILayout.Button("Place to Ground")) { //for each waypoint of this path foreach (Transform trans in waypoints) { //define ray to cast downwards waypoint position Ray ray = new Ray(trans.position + new Vector3(0, 2f, 0), -Vector3.up); Undo.RecordObject(trans, ""); RaycastHit hit; //cast ray against ground, if it hit: if (Physics.Raycast(ray, out hit, 100)) { //position y values of waypoint to hit point trans.position = hit.point; } //also try to raycast against 2D colliders RaycastHit2D hit2D = Physics2D.Raycast(ray.origin, -Vector2.up, 100); if (hit2D) { trans.position = new Vector3(hit2D.point.x, hit2D.point.y, trans.position.z); } } } EditorGUILayout.Space(); //invert direction of whole path if (GUILayout.Button("Invert Direction")) { Undo.RecordObjects(waypoints, ""); //to reverse the whole path we need to know where the waypoints were before //for this purpose a new copy must be created Vector3[] waypointCopy = new Vector3[waypoints.Length]; for (int i = 0; i < waypoints.Length; i++) { waypointCopy[i] = waypoints[i].position; } //looping over the array in reversed order for (int i = 0; i < waypoints.Length; i++) { waypoints[i].position = waypointCopy[waypointCopy.Length - 1 - i]; } } EditorGUILayout.Space(); //draw object field for waypoint prefab EditorGUILayout.PropertyField(m_WaypointPref); //replace all waypoints with the prefab if (GUILayout.Button("Replace Waypoints with Object")) { if (m_WaypointPref == null) { Debug.LogWarning("No replace object set. Cancelling."); return; } ReplaceWaypoints(); } //we push our modified variables back to our serialized object m_Object.ApplyModifiedProperties(); }
public override void OnInspectorGUI() { //show default variables of manager DrawDefaultInspector(); //get manager reference script = (WaypointManager)target; EditorGUILayout.LabelField("", GUI.skin.horizontalSlider); //get sceneview to auto-detect 2D mode SceneView view = GetSceneView(); mode2D = view.in2DMode; EditorGUILayout.Space(); EditorGUILayout.BeginHorizontal(); //draw path text label GUILayout.Label("Enter Path Name: ", GUILayout.Height(15)); //display text field for creating a path with that name pathName = EditorGUILayout.TextField(pathName, GUILayout.Height(15)); EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); EditorGUILayout.BeginHorizontal(); //draw path type selection enum GUILayout.Label("Select Path Type: ", GUILayout.Height(15)); pathType = (PathType)EditorGUILayout.EnumPopup(pathType); EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); //display label of current mode if (mode2D) { GUILayout.Label("2D Mode Detected.", GUILayout.Height(15)); } else { GUILayout.Label("3D Mode Detected.", GUILayout.Height(15)); } EditorGUILayout.Space(); //draw path creation button if (!placing && GUILayout.Button("Start Path", GUILayout.Height(40))) { if (pathName == "") { EditorUtility.DisplayDialog("No Path Name", "Please enter a unique name for your path.", "Ok"); return; } if (script.transform.FindChild(pathName) != null) { if (EditorUtility.DisplayDialog("Path Exists Already", "A path with this name exists already.\n\nWould you like to edit it?", "Ok", "Cancel")) { Selection.activeTransform = script.transform.FindChild(pathName); } return; } //create a new container transform which will hold all new waypoints path = new GameObject(pathName); //reset position and parent container gameobject to this manager gameobject path.transform.position = script.gameObject.transform.position; path.transform.parent = script.gameObject.transform; StartPath(); //we passed all prior checks, toggle waypoint placement placing = true; //focus sceneview for placement view.Focus(); } GUI.backgroundColor = Color.yellow; //finish path button if (placing && GUILayout.Button("Finish Editing", GUILayout.Height(40))) { FinishPath(); } GUI.backgroundColor = Color.white; EditorGUILayout.Space(); //draw instructions GUILayout.TextArea("Hint:\nEnter a unique name for your path, " + "then press 'Start Path' to begin placement mode. Press '" + script.placementKey + "' on your keyboard to place new waypoints in the Scene view. In 3D Mode " + "you have to place waypoints onto game objects with colliders. You can " + "also place waypoints at the current scene view camera position by pressing '" + script.viewPlacementKey + "'.\n\nPress 'Finish Editing' to end your path."); }
//auto-add to WaypointManager void Awake() { WaypointManager.AddPath(gameObject); }
//if this path is selected, display small info boxes above all waypoint positions //also display handles for the waypoints void OnSceneGUI() { //again, get waypoint array var waypoints = GetWaypointArray(); //do not execute further code if we have no waypoints defined //(just to make sure, practically this can not occur) if (waypoints.Length == 0) { return; } Vector3 wpPos = Vector3.zero; float size = 1f; //loop through waypoint array for (int i = 0; i < waypoints.Length; i++) { if (!waypoints[i]) { continue; } wpPos = waypoints[i].position; size = HandleUtility.GetHandleSize(wpPos) * 0.4f; //do not draw waypoint header if too far away if (size < 3f) { //begin 2D GUI block Handles.BeginGUI(); //translate waypoint vector3 position in world space into a position on the screen var guiPoint = HandleUtility.WorldToGUIPoint(wpPos); //create rectangle with that positions and do some offset var rect = new Rect(guiPoint.x - 50.0f, guiPoint.y - 40, 100, 20); //draw box at position with current waypoint name GUI.Box(rect, waypoints[i].name); Handles.EndGUI(); //end GUI block } //draw handles per waypoint, clamp size Handles.color = m_Color2.colorValue; size = Mathf.Clamp(size, 0, 1.2f); Vector3 newPos = Handles.FreeMoveHandle(wpPos, Quaternion.identity, size, Vector3.zero, Handles.SphereCap); Handles.RadiusHandle(Quaternion.identity, wpPos, size / 2); if (wpPos != newPos) { Undo.RecordObject(waypoints[i], "Move Handles"); waypoints[i].position = newPos; } } //waypoint direction handles drawing if (!m_Check2.boolValue) { return; } Vector3[] pathPoints = new Vector3[waypoints.Length]; for (int i = 0; i < pathPoints.Length; i++) { pathPoints[i] = waypoints[i].position; } //create list of path segments (list of Vector3 list) List <List <Vector3> > segments = new List <List <Vector3> >(); int curIndex = 0; float lerpVal = 0f; //differ between linear and curved display switch (m_Check1.boolValue) { case true: //convert waypoints to curved path points pathPoints = WaypointManager.GetCurved(pathPoints); for (int i = 0; i < waypoints.Length - 1; i++) { //loop over path points to find single segments segments.Add(new List <Vector3>()); for (int j = curIndex; j < pathPoints.Length; j++) { //the segment ends here, continue with new segment if (pathPoints[j] == waypoints[i + 1].position) { curIndex = j; break; } //add path point to current segment segments[i].Add(pathPoints[j]); } } break; case false: //detail for arrows between waypoints int lerpMax = 16; //loop over waypoints to add intermediary points for (int i = 0; i < waypoints.Length - 1; i++) { segments.Add(new List <Vector3>()); for (int j = 0; j < lerpMax; j++) { //linear lerp between waypoints to get additional points for drawing arrows at segments[i].Add(Vector3.Lerp(pathPoints[i], pathPoints[i + 1], j / (float)lerpMax)); } } break; } //loop over segments for (int i = 0; i < segments.Count; i++) { //loop over single positions on the segment for (int j = 0; j < segments[i].Count; j++) { //get current lerp value for interpolating rotation //draw arrow handle on current position with interpolated rotation size = Mathf.Clamp(HandleUtility.GetHandleSize(segments[i][j]) * 0.4f, 0, 1.2f); lerpVal = j / (float)segments[i].Count; Handles.ArrowCap(0, segments[i][j], Quaternion.Lerp(waypoints[i].rotation, waypoints[i + 1].rotation, lerpVal) * Quaternion.Euler(0, 90, 0), size); } } }
public override void OnInspectorGUI() { //don't draw inspector fields if the path contains less than 2 points //(a path with less than 2 points really isn't a path) if (script.bPoints.Count < 2) { return; } //checkbox field to enable editable path properties script.showHandles = EditorGUILayout.Toggle("Show Handles", script.showHandles); //checkbox field for toggling control point connectedness script.connectHandles = EditorGUILayout.Toggle("Connect Handles", script.connectHandles); //checkbox field for drawing gizmo path lines script.drawCurved = EditorGUILayout.Toggle("Draw Smooth Lines", script.drawCurved); //create new color fields for editing path gizmo colors script.color1 = EditorGUILayout.ColorField("Color1", script.color1); script.color2 = EditorGUILayout.ColorField("Color2", script.color2); script.color3 = EditorGUILayout.ColorField("Color3", script.color3); //calculate path length of all waypoints float pathLength = WaypointManager.GetPathLength(script.pathPoints); //path length label, show calculated path length GUILayout.Label("Path Length: " + pathLength); float thisDetail = script.pathDetail; //slider to modify the smoothing factor of the final path, //round because of path point imprecision placement (micro loops) script.pathDetail = EditorGUILayout.Slider("Path Detail", script.pathDetail, 0.5f, 10); script.pathDetail = Mathf.Round(script.pathDetail * 10f) / 10f; //toggle custom detail when modifying the whole path if (thisDetail != script.pathDetail) { script.customDetail = false; } //draw custom detail settings EditorGUILayout.Space(); DetailSettings(); EditorGUILayout.Space(); //waypoint index header GUILayout.Label("Waypoints: ", EditorStyles.boldLabel); //loop through the waypoint array for (int i = 0; i < script.bPoints.Count; i++) { GUILayout.BeginHorizontal(); //indicate each array slot with index number in front of it GUILayout.Label(i + ".", GUILayout.Width(20)); //create an object field for every waypoint EditorGUILayout.ObjectField(script.bPoints[i].wp, typeof(Transform), true); //display an "Add Waypoint" button for every array row except the last one //on click we call AddWaypointAtIndex() to insert a new waypoint slot AFTER the selected slot if (i < script.bPoints.Count && GUILayout.Button("+", GUILayout.Width(30f))) { AddWaypointAtIndex(i); break; } //display an "Remove Waypoint" button for every array row except the first and last one //on click we call RemoveWaypointAtIndex() to delete the selected waypoint slot if (i > 0 && i < script.bPoints.Count - 1 && GUILayout.Button("-", GUILayout.Width(30f))) { RemoveWaypointAtIndex(i); break; } GUILayout.EndHorizontal(); } EditorGUILayout.Space(); EditorGUILayout.BeginHorizontal(); //button to rename waypoints to current index order if (GUILayout.Button("Rename Waypoints")) { string wpName = string.Empty; string[] nameSplit; for (int i = 0; i < script.bPoints.Count; i++) { //cache name and split into strings wpName = script.bPoints[i].wp.name; nameSplit = wpName.Split(' '); //ignore custom names and just rename if (!script.skipCustomNames) { wpName = "Waypoint " + i; } else if (nameSplit.Length == 2 && nameSplit[0] == "Waypoint") { //try parsing the current index and rename, //not ignoring custom names here int index; if (int.TryParse(nameSplit[1], out index)) { wpName = nameSplit[0] + " " + i; } } //set the desired index or leave it script.bPoints[i].wp.name = wpName; } } EditorGUILayout.LabelField("Skip Custom", GUILayout.Width(80)); script.skipCustomNames = EditorGUILayout.Toggle(script.skipCustomNames, GUILayout.Width(20)); EditorGUILayout.EndHorizontal(); //button to move all waypoints down to the ground if (GUILayout.Button("Place to Ground")) { //for each waypoint of this path foreach (BezierPoint bp in script.bPoints) { //define ray to cast downwards waypoint position Ray ray = new Ray(bp.wp.position + new Vector3(0, 2f, 0), -Vector3.up); Undo.RecordObject(bp.wp, "PlaceToGround"); RaycastHit hit; //cast ray against ground, if it hit: if (Physics.Raycast(ray, out hit, 100)) { //position waypoint to hit point bp.wp.position = hit.point; } //also try to raycast against 2D colliders RaycastHit2D hit2D = Physics2D.Raycast(ray.origin, -Vector2.up, 100); if (hit2D) { bp.wp.position = new Vector3(hit2D.point.x, hit2D.point.y, bp.wp.position.z); } } } //invert direction of whole path if (GUILayout.Button("Invert Direction")) { Undo.RecordObject(script, "Invert"); //to reverse the whole path we need to know where the waypoints were before //for this purpose a new copy must be created BezierPoint[] waypointCache = new BezierPoint[script.bPoints.Count]; for (int i = 0; i < waypointCache.Length; i++) { waypointCache[i] = script.bPoints[i]; } //reverse order based on the old list for (int i = 0; i < waypointCache.Length; i++) { BezierPoint currentPoint = script.bPoints[waypointCache.Length - 1 - i]; script.bPoints[waypointCache.Length - 1 - i] = waypointCache[i]; Vector3 leftHandle = currentPoint.cp[0].position; Undo.RecordObject(currentPoint.cp[0], "Invert"); Undo.RecordObject(currentPoint.cp[1], "Invert"); currentPoint.cp[0].position = currentPoint.cp[1].position; currentPoint.cp[1].position = leftHandle; } } EditorGUILayout.Space(); //draw object field for new waypoint object script.replaceObject = (GameObject)EditorGUILayout.ObjectField("Replace Object", script.replaceObject, typeof(GameObject), true); //replace all waypoints with the prefab if (GUILayout.Button("Replace Waypoints with Object")) { ReplaceWaypoints(); } //recalculate on inspector changes if (GUI.changed) { script.CalculatePath(); EditorUtility.SetDirty(target); } }
public override void OnInspectorGUI() { //show default variables of manager DrawDefaultInspector(); //get manager reference script = (WaypointManager)target; //get sceneview to auto-detect 2D mode SceneView view = GetSceneView(); mode2D = view.in2DMode; EditorGUILayout.Space(); EditorGUILayout.BeginHorizontal(); //draw path text label GUILayout.Label("Enter Path Name: ", GUILayout.Height(15)); //display text field for creating a path with that name pathName = EditorGUILayout.TextField(pathName, GUILayout.Height(15)); EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); EditorGUILayout.BeginHorizontal(); //draw path type selection enum GUILayout.Label("Select Path Type: ", GUILayout.Height(15)); pathType = (PathType)EditorGUILayout.EnumPopup(pathType); EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); //display label of current mode if (mode2D) { GUILayout.Label("2D Mode Detected.", GUILayout.Height(15)); } else { GUILayout.Label("3D Mode Detected.", GUILayout.Height(15)); } EditorGUILayout.Space(); //draw path creation button if (!placing && GUILayout.Button("Start Path", GUILayout.Height(40))) { if (pathName == "") { Debug.LogWarning("No path name defined. Cancelling."); return; } if (script.transform.Find(pathName) != null) { Debug.LogWarning("Path name already given. Cancelling."); return; } //create a new container transform which will hold all new waypoints path = new GameObject(pathName); //reset position and parent container gameobject to this manager gameobject path.transform.position = script.gameObject.transform.position; path.transform.parent = script.gameObject.transform; StartPath(); //we passed all prior checks, toggle waypoint placement placing = true; //focus sceneview for placement view.Focus(); } GUI.backgroundColor = Color.yellow; //finish path button if (placing && GUILayout.Button("Finish Editing", GUILayout.Height(40))) { if (wpList.Count < 2) { Debug.LogWarning("Not enough waypoints placed. Cancelling."); //if we have created a path already, destroy it again if (path) { DestroyImmediate(path); } } //toggle placement off placing = false; //clear list with temporary waypoint references, //we only needed this for getting the waypoint count wpList.Clear(); //reset path name input field pathName = ""; //make the new path the active selection Selection.activeGameObject = path; } GUI.backgroundColor = Color.white; EditorGUILayout.Space(); //draw instructions GUILayout.TextArea("Hint:\nPress 'Start Path' to begin a new path, then press 'p' on " + "your keyboard to place new waypoints in the SceneView. In 3D Mode " + "you have to place waypoints onto objects with colliders. You can " + "also place waypoints at the scene view position by pressing 'c'." + "\n\nPress 'Finish Editing' to end your path."); }
//called whenever the inspector gui gets rendered public override void OnInspectorGUI() { //don't draw inspector fields if the path contains less than 2 points //(a path with less than 2 points really isn't a path) if (m_WaypointsCount.intValue < 2) { return; } //this pulls the relative variables from unity runtime and stores them in the object m_Object.Update(); //create new checkboxes for path gizmo property m_Check1.boolValue = EditorGUILayout.Toggle("Draw Smooth Lines", m_Check1.boolValue); //m_Check2.boolValue = EditorGUILayout.Toggle("Draw Direction Handles", m_Check2.boolValue); //create new property fields for editing waypoint gizmo colors EditorGUILayout.PropertyField(m_Color1); EditorGUILayout.PropertyField(m_Color2); //get waypoint array var waypoints = GetWaypointArray(); //calculate path length of all waypoints Vector3[] wpPositions = new Vector3[waypoints.Length]; for (int i = 0; i < waypoints.Length; i++) { wpPositions[i] = waypoints[i].position; } float pathLength = WaypointManager.GetPathLength(wpPositions); //path length label, show calculated path length GUILayout.Label("Path Length: " + pathLength); //waypoint index header GUILayout.Label("Waypoints: ", EditorStyles.boldLabel); //loop through the waypoint array for (int i = 0; i < waypoints.Length; i++) { GUILayout.BeginHorizontal(); //indicate each array slot with index number in front of it GUILayout.Label(i + ".", GUILayout.Width(20)); //create an object field for every waypoint EditorGUILayout.ObjectField(waypoints[i], typeof(Transform), true); //display an "Add Waypoint" button for every array row except the last one if (i < waypoints.Length && GUILayout.Button("+", GUILayout.Width(30f))) { AddWaypointAtIndex(i); break; } //display an "Remove Waypoint" button for every array row except the first and last one if (i > 0 && i < waypoints.Length - 1 && GUILayout.Button("-", GUILayout.Width(30f))) { RemoveWaypointAtIndex(i); break; } GUILayout.EndHorizontal(); } EditorGUILayout.Space(); EditorGUILayout.BeginHorizontal(); //button to rename waypoints to current index order if (GUILayout.Button("Rename Waypoints")) { //disabled because of a Unity bug that crashes the editor //this is taken directly from the docs, thank you Unity. //http://docs.unity3d.com/ScriptReference/Undo.RegisterCompleteObjectUndo.html //Undo.RegisterCompleteObjectUndo(waypoints[0].gameObject, "Rename Waypoints"); string wpName = string.Empty; string[] nameSplit; for (int i = 0; i < waypoints.Length; i++) { //cache name and split into strings wpName = waypoints[i].name; nameSplit = wpName.Split(' '); //ignore custom names and just rename if (!m_SkipNames.boolValue) { wpName = "Waypoint " + i; } else if (nameSplit.Length == 2 && nameSplit[0] == "Waypoint") { //try parsing the current index and rename, //not ignoring custom names here int index; if (int.TryParse(nameSplit[1], out index)) { wpName = nameSplit[0] + " " + i; } } //set the desired index or leave it waypoints[i].name = wpName; } } EditorGUILayout.LabelField("Skip Custom", GUILayout.Width(80)); m_SkipNames.boolValue = EditorGUILayout.Toggle(m_SkipNames.boolValue, GUILayout.Width(20)); EditorGUILayout.EndHorizontal(); //button to move all waypoints down to the ground if (GUILayout.Button("Place to Ground")) { //for each waypoint of this path foreach (Transform trans in waypoints) { //define ray to cast downwards waypoint position Ray ray = new Ray(trans.position + new Vector3(0, 2f, 0), -Vector3.up); Undo.RecordObject(trans, "Place To Ground"); RaycastHit hit; //cast ray against ground, if it hit: if (Physics.Raycast(ray, out hit, 100)) { //position y values of waypoint to hit point trans.position = hit.point; } //also try to raycast against 2D colliders RaycastHit2D hit2D = Physics2D.Raycast(ray.origin, -Vector2.up, 100); if (hit2D) { trans.position = new Vector3(hit2D.point.x, hit2D.point.y, trans.position.z); } } } //invert direction of whole path if (GUILayout.Button("Invert Direction")) { Undo.RecordObjects(waypoints, "Invert Direction"); //to reverse the whole path we need to know where the waypoints were before //for this purpose a new copy must be created Vector3[] waypointCopy = new Vector3[waypoints.Length]; for (int i = 0; i < waypoints.Length; i++) { waypointCopy[i] = waypoints[i].position; } //looping over the array in reversed order for (int i = 0; i < waypoints.Length; i++) { waypoints[i].position = waypointCopy[waypointCopy.Length - 1 - i]; } } EditorGUILayout.Space(); //draw object field for waypoint prefab EditorGUILayout.PropertyField(m_WaypointPref); //replace all waypoints with the prefab if (GUILayout.Button("Replace Waypoints with Object")) { if (m_WaypointPref == null) { Debug.LogWarning("No replace object set. Cancelling."); return; } ReplaceWaypoints(); } //we push our modified variables back to our serialized object m_Object.ApplyModifiedProperties(); }
public override void OnInspectorGUI() { //don't draw inspector fields if the path contains less than 2 points //(a path with less than 2 points really isn't a path) if (script.bPoints.Count < 2) { //button to create path manually if (GUILayout.Button("Create Path from Children")) { Undo.RecordObject(script, "Create Path"); script.Create(); SceneView.RepaintAll(); } return; } //create new checkboxes for path gizmo property script.showHandles = EditorGUILayout.Toggle("Show Handles", script.showHandles); script.connectHandles = EditorGUILayout.Toggle("Connect Handles", script.connectHandles); script.drawCurved = EditorGUILayout.Toggle("Draw Smooth Lines", script.drawCurved); script.drawDirection = EditorGUILayout.Toggle("Draw Direction", script.drawDirection); //create new color fields for editing path gizmo colors script.color1 = EditorGUILayout.ColorField("Color1", script.color1); script.color2 = EditorGUILayout.ColorField("Color2", script.color2); script.color3 = EditorGUILayout.ColorField("Color3", script.color3); //calculate path length of all waypoints float pathLength = WaypointManager.GetPathLength(script.pathPoints); GUILayout.Label("Path Length: " + pathLength); float thisDetail = script.pathDetail; //slider to modify the smoothing factor of the final path, //round because of path point imprecision placement (micro loops) script.pathDetail = EditorGUILayout.Slider("Path Detail", script.pathDetail, 0.5f, 10); script.pathDetail = Mathf.Round(script.pathDetail * 10f) / 10f; //toggle custom detail when modifying the whole path if (thisDetail != script.pathDetail) { script.customDetail = false; } //draw custom detail settings DetailSettings(); //button for switching over to the WaypointManager for further path editing if (GUILayout.Button("Continue Editing")) { Selection.activeGameObject = (GameObject.FindObjectOfType(typeof(WaypointManager)) as WaypointManager).gameObject; WaypointEditor.ContinuePath(script); } //more path modifiers DrawPathOptions(); EditorGUILayout.Space(); //waypoint index header GUILayout.Label("Waypoints: ", EditorStyles.boldLabel); //loop through the waypoint array for (int i = 0; i < script.bPoints.Count; i++) { GUILayout.BeginHorizontal(); //indicate each array slot with index number in front of it GUILayout.Label(i + ".", GUILayout.Width(20)); //create an object field for every waypoint EditorGUILayout.ObjectField(script.bPoints[i].wp, typeof(Transform), true); //display an "Add Waypoint" button for every array row except the last one //on click we call AddWaypointAtIndex() to insert a new waypoint slot AFTER the selected slot if (i < script.bPoints.Count && GUILayout.Button("+", GUILayout.Width(30f))) { AddWaypointAtIndex(i); break; } //display an "Remove Waypoint" button for every array row except the first and last one //on click we call RemoveWaypointAtIndex() to delete the selected waypoint slot if (i > 0 && i < script.bPoints.Count - 1 && GUILayout.Button("-", GUILayout.Width(30f))) { RemoveWaypointAtIndex(i); break; } GUILayout.EndHorizontal(); } //recalculate on inspector changes if (GUI.changed) { script.CalculatePath(); EditorUtility.SetDirty(target); } }
public override void OnInspectorGUI() { //show default variables of manager DrawDefaultInspector(); //get manager reference script = (WaypointManager)target; //get sceneview to auto-detect 2D mode SceneView view = SceneView.currentDrawingSceneView; if (view == null) { view = EditorWindow.GetWindow <SceneView>("Scene", false); } mode2D = view.in2DMode; EditorGUIUtility.LookLikeControls(); EditorGUILayout.Space(); EditorGUILayout.BeginHorizontal(); //draw path text label GUILayout.Label("Enter Path Name: ", GUILayout.Height(15)); //display text field for creating a path with that name pathName = EditorGUILayout.TextField(pathName, GUILayout.Height(15)); EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); EditorGUILayout.BeginHorizontal(); //draw path type selection enum GUILayout.Label("Select Path Type: ", GUILayout.Height(15)); pathType = (PathType)EditorGUILayout.EnumPopup(pathType); EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); //display label of current mode if (mode2D) { GUILayout.Label("2D Mode Detected.", GUILayout.Height(15)); } else { GUILayout.Label("3D Mode Detected.", GUILayout.Height(15)); } EditorGUILayout.Space(); //draw path creation button if (!placing && GUILayout.Button("Start Path", GUILayout.Height(40))) { if (pathName == "") { Debug.LogWarning("No path name defined. Cancelling."); return; } if (script.transform.Find(pathName) != null) { Debug.LogWarning("Path name already given. Cancelling."); return; } //create a new container transform which will hold all new waypoints path = new GameObject(pathName); //reset position and parent container gameobject to this manager gameobject path.transform.position = script.gameObject.transform.position; path.transform.parent = script.gameObject.transform; StartPath(); //we passed all prior checks, toggle waypoint placement placing = true; //focus sceneview for placement if (view != null) { view.Focus(); } // SceneView.currentDrawingSceneView.Focus(); } if (!placing && GUILayout.Button("Export Path", GUILayout.Height(40))) { string filepath = EditorUtility.SaveFilePanelInProject("Save Path", "PathInfo", "csv", "OKOK"); LogManager.Log(filepath); string fileName = filepath; //文件名字 StringBuilder sb = new StringBuilder(); //offset sb.Append("patrolId").Append(','); sb.Append("patrolPlan").Append(','); sb.Append("patrolX").Append(','); sb.Append("patrolY").Append("\r\n"); int totalCount = 0; PathManager[] pathes = script.GetComponentsInChildren <PathManager>(); for (int i = 0; i < pathes.Length; ++i) { sb.Append('#').Append(pathes[i].name).Append(',').Append(pathes[i].transform.position.y).Append("\r\n"); Vector3[] points = pathes[i].GetPathPoints(); for (int j = 0; j < points.Length; ++j) { totalCount++; sb.Append(totalCount).Append(','); sb.Append(i).Append(','); sb.Append(points[j].x).Append(','); sb.Append(points[j].z).Append("\r\n"); } } //要写的数据源 SaveTextFile(filepath, sb.ToString()); } if (!placing && GUILayout.Button("Import", GUILayout.Height(40))) { string filepath = EditorUtility.OpenFilePanel("Load pathes", Application.dataPath, "csv"); if (filepath != null) { StreamReader reader = new StreamReader(filepath, new UTF8Encoding(false)); if (reader != null) { string content = reader.ReadToEnd(); int readPos = 0; //skip the first line string skipLine = EditorUtils.readLine(content, ref readPos); List <string> kv = null; PathManager manager = null; int pointCount = 0; float currentY = 0f; while (readPos < content.Length) { string lineNew = EditorUtils.readLine(content, ref readPos); //new path if (lineNew[0] == '#') { int noUse = 0; kv = GameAssist.readCsvLine(lineNew, ref noUse); string readpathName = kv[0].Substring(1); float.TryParse(kv[1], out currentY); path = new GameObject(readpathName); //reset position and parent container gameobject to this manager gameobject path.transform.position = script.gameObject.transform.position; path.transform.parent = script.gameObject.transform; StartPath(); wpList.Clear(); } else { int a = 0; kv = GameAssist.readCsvLine(lineNew, ref a); float x = 0f; float.TryParse(kv[2], out x); float z = 0f; float.TryParse(kv[3], out z); PlaceWaypoint(new Vector3(x, currentY, z)); } } } } } if (!placing && GUILayout.Button("CreateColliders", GUILayout.Height(40))) { UnityEngine.Object prefab = AssetDatabase.LoadAssetAtPath("Assets/PathEditor/Cube.prefab", typeof(UnityEngine.Object)); GameObject parent = GameObject.Find("WalkColliders"); Texture2D tex = (Texture2D)AssetDatabase.LoadAssetAtPath("Assets/CameraPath3/Icons/options.png", typeof(Texture2D)); if (parent == null) { parent = new GameObject("WalkColliders"); } PathManager[] pathes = script.GetComponentsInChildren <PathManager>(); for (int i = 0; i < pathes.Length; ++i) { Vector3[] points = pathes[i].GetPathPoints(); int pointC = points.Length; int loopcount = pointC; //不是关闭类型的,不生成最后一个点到初始点的连线 if (pathes[i].closure == false) { loopcount = pointC - 1; } for (int j = 0; j < loopcount; ++j) { Vector3 nextPos = points[(j + 1) % pointC]; Vector3 middlePos = (points[j] + nextPos) * 0.5f; GameObject collider = GameObject.Instantiate(prefab, middlePos, Quaternion.identity) as GameObject; Vector3 lookPos = nextPos; lookPos.y = middlePos.y; collider.transform.LookAt(lookPos); collider.transform.parent = parent.transform; Vector3 setScale = collider.transform.localScale; setScale.z = (nextPos - points[j]).magnitude; collider.transform.localScale = setScale; } } } GUI.backgroundColor = Color.yellow; //finish path button if (placing && GUILayout.Button("Finish Editing", GUILayout.Height(40))) { if (wpList.Count < 2) { Debug.LogWarning("Not enough waypoints placed. Cancelling."); //if we have created a path already, destroy it again if (path) { DestroyImmediate(path); } } //toggle placement off placing = false; //clear list with temporary waypoint references, //we only needed this for getting the waypoint count wpList.Clear(); //reset path name input field pathName = ""; //make the new path the active selection Selection.activeGameObject = path; } GUI.backgroundColor = Color.white; EditorGUILayout.Space(); //draw instructions GUILayout.TextArea("Hint:\nPress 'Start Path' to begin a new path, then press 'p' " + "on your keyboard to place waypoints in the SceneView. In 3D Mode " + "you have to place waypoints onto objects with colliders." + "\n\nPress 'Finish Editing' to end your path."); }
//if this path is selected, display small info boxes above all waypoint positions //also display handles for the waypoints void OnSceneGUI() { //again, get waypoint array var waypoints = GetWaypointArray(); //do not execute further code if we have no waypoints defined //(just to make sure, practically this can not occur) if (waypoints.Length == 0) { return; } Vector3 wpPos = Vector3.zero; float size = 1f; //loop through waypoint array for (int i = 0; i < waypoints.Length; i++) { if (!waypoints[i]) { continue; } wpPos = waypoints[i].position; size = HandleUtility.GetHandleSize(wpPos) * 0.4f; //do not draw waypoint header if too far away if (size < 3f) { //begin 2D GUI block Handles.BeginGUI(); //translate waypoint vector3 position in world space into a position on the screen var guiPoint = HandleUtility.WorldToGUIPoint(wpPos); //create rectangle with that positions and do some offset var rect = new Rect(guiPoint.x - 50.0f, guiPoint.y - 40, 100, 20); //draw box at position with current waypoint name GUI.Box(rect, waypoints[i].name); Handles.EndGUI(); //end GUI block } //draw handles per waypoint, clamp size Handles.color = m_Color2.colorValue; size = Mathf.Clamp(size, 0, 1.2f); Handles.FreeMoveHandle(wpPos, Quaternion.identity, size, Vector3.zero, (controlID, position, rotation, hSize, eventType) => { Handles.SphereHandleCap(controlID, position, rotation, hSize, eventType); if (controlID == GUIUtility.hotControl && GUIUtility.hotControl != 0) { activeNode = i; } }); Handles.RadiusHandle(waypoints[i].rotation, wpPos, size / 2); } if (activeNode > -1) { wpPos = waypoints[activeNode].position; Quaternion wpRot = waypoints[activeNode].rotation; switch (Tools.current) { case Tool.Move: if (Tools.pivotRotation == PivotRotation.Global) { wpRot = Quaternion.identity; } Vector3 newPos = Handles.PositionHandle(wpPos, wpRot); if (wpPos != newPos) { Undo.RecordObject(waypoints[activeNode], "Move Handle"); waypoints[activeNode].position = newPos; } break; case Tool.Rotate: Quaternion newRot = Handles.RotationHandle(wpRot, wpPos); if (wpRot != newRot) { Undo.RecordObject(waypoints[activeNode], "Rotate Handle"); waypoints[activeNode].rotation = newRot; } break; } } //waypoint direction handles drawing if (!m_Check2.boolValue) { return; } Vector3[] pathPoints = new Vector3[waypoints.Length]; for (int i = 0; i < pathPoints.Length; i++) { pathPoints[i] = waypoints[i].position; } //create list of path segments (list of Vector3 list) List <List <Vector3> > segments = new List <List <Vector3> >(); int curIndex = 0; float lerpVal = 0f; //differ between linear and curved display switch (m_Check1.boolValue) { case true: //convert waypoints to curved path points pathPoints = WaypointManager.GetCurved(pathPoints); //calculate approximate path point amount per segment int detail = Mathf.FloorToInt((pathPoints.Length - 1f) / (waypoints.Length - 1f)); for (int i = 0; i < waypoints.Length - 1; i++) { float dist = Mathf.Infinity; //loop over path points to find single segments segments.Add(new List <Vector3>()); //we are not checking for absolute path points on standard paths, because //path points could also be located before or after waypoint positions. //instead a minimum distance is searched which marks the nearest path point for (int j = curIndex; j < pathPoints.Length; j++) { //add path point to current segment segments[i].Add(pathPoints[j]); //start looking for distance after a certain amount of path points of this segment if (j >= (i + 1) * detail) { //calculate distance of current path point to waypoint float pointDist = Vector3.Distance(waypoints[i].position, pathPoints[j]); //we are getting closer to the waypoint if (pointDist < dist) { dist = pointDist; } else { //current path point is more far away than the last one //the segment ends here, continue with new segment curIndex = j + 1; break; } } } } break; case false: //detail for arrows between waypoints int lerpMax = 16; //loop over waypoints to add intermediary points for (int i = 0; i < waypoints.Length - 1; i++) { segments.Add(new List <Vector3>()); for (int j = 0; j < lerpMax; j++) { //linear lerp between waypoints to get additional points for drawing arrows at segments[i].Add(Vector3.Lerp(pathPoints[i], pathPoints[i + 1], j / (float)lerpMax)); } } break; } //loop over segments for (int i = 0; i < segments.Count; i++) { //loop over single positions on the segment for (int j = 0; j < segments[i].Count; j++) { //get current lerp value for interpolating rotation //draw arrow handle on current position with interpolated rotation size = Mathf.Clamp(HandleUtility.GetHandleSize(segments[i][j]) * 0.4f, 0, 1.2f); lerpVal = j / (float)segments[i].Count; Handles.ArrowHandleCap(0, segments[i][j], Quaternion.Lerp(waypoints[i].rotation, waypoints[i + 1].rotation, lerpVal), size, EventType.Repaint); } } }
//called whenever the inspector gui gets rendered public override void OnInspectorGUI() { //this pulls the relative variables from unity runtime and stores them in the object m_Object.Update(); //get waypoint array var waypoints = GetWaypointArray(); //don't draw inspector fields if the path contains less than 2 points //(a path with less than 2 points really isn't a path) if (m_WaypointsCount.intValue < 2) { //button to create path manually if (GUILayout.Button("Create Path from Children")) { Undo.RecordObjects(waypoints, "Create Path"); (m_Object.targetObject as PathManager).Create(); SceneView.RepaintAll(); } return; } //create new checkboxes for path gizmo property m_Check1.boolValue = EditorGUILayout.Toggle("Draw Smooth Lines", m_Check1.boolValue); m_Check2.boolValue = EditorGUILayout.Toggle("Draw Direction", m_Check2.boolValue); //create new property fields for editing waypoint gizmo colors EditorGUILayout.PropertyField(m_Color1); EditorGUILayout.PropertyField(m_Color2); //calculate path length of all waypoints Vector3[] wpPositions = new Vector3[waypoints.Length]; for (int i = 0; i < waypoints.Length; i++) { wpPositions[i] = waypoints[i].position; } float pathLength = WaypointManager.GetPathLength(wpPositions); //path length label, show calculated path length GUILayout.Label("Path Length: " + pathLength); //button for switching over to the WaypointManager for further path editing if (GUILayout.Button("Continue Editing")) { Selection.activeGameObject = (GameObject.FindObjectOfType(typeof(WaypointManager)) as WaypointManager).gameObject; WaypointEditor.ContinuePath(m_Object.targetObject as PathManager); } //more path modifiers DrawPathOptions(); EditorGUILayout.Space(); //waypoint index header GUILayout.Label("Waypoints: ", EditorStyles.boldLabel); //loop through the waypoint array for (int i = 0; i < waypoints.Length; i++) { GUILayout.BeginHorizontal(); //indicate each array slot with index number in front of it GUILayout.Label(i + ".", GUILayout.Width(20)); //create an object field for every waypoint EditorGUILayout.ObjectField(waypoints[i], typeof(Transform), true); //display an "Add Waypoint" button for every array row except the last one if (i < waypoints.Length && GUILayout.Button("+", GUILayout.Width(30f))) { AddWaypointAtIndex(i); break; } //display an "Remove Waypoint" button for every array row except the first and last one if (i > 0 && i < waypoints.Length - 1 && GUILayout.Button("-", GUILayout.Width(30f))) { RemoveWaypointAtIndex(i); break; } GUILayout.EndHorizontal(); } //we push our modified variables back to our serialized object m_Object.ApplyModifiedProperties(); }
public override void OnInspectorGUI() { editPlane = target as GridPlane; //show default variables of manager DrawDefaultInspector(); //get manager reference EditorGUIUtility.LookLikeControls(); EditorGUILayout.Space(); EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("One Point", GUILayout.Height(40))) { editPlane.SetBrushType(0); SceneView.currentDrawingSceneView.Focus(); } if (GUILayout.Button("three Point", GUILayout.Height(40))) { editPlane.SetBrushType(1); SceneView.currentDrawingSceneView.Focus(); } EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); if (GUILayout.Button("Generate", GUILayout.Height(40))) { editPlane.GenerateMesh(); } //draw path creation button GUI.backgroundColor = Color.yellow; if (!placing && GUILayout.Button("Brush", GUILayout.Height(40))) { //we passed all prior checks, toggle waypoint placement placing = true; //focus sceneview for placement SceneView.currentDrawingSceneView.Focus(); } if (placing && GUILayout.Button("Erase", GUILayout.Height(40))) { //we passed all prior checks, toggle waypoint placement placing = false; //focus sceneview for placement SceneView.currentDrawingSceneView.Focus(); } GUI.backgroundColor = Color.white; if (GUILayout.Button("ExportCollision", GUILayout.Height(40))) { string filepath = EditorUtility.SaveFilePanelInProject("Save Map", "CollisionInfo", "bytes", "OKOK"); LogManager.Log(filepath); FileStream fs = new FileStream(filepath, FileMode.Create, FileAccess.Write); BinaryWriter bw = new BinaryWriter(fs); // string fileName = filepath;//文件名字 Vector3 offset = editPlane.transform.position; //write offset x FP offsetX = (FP)(offset.x); bw.Write(offsetX.RawValue); //write offset z FP offsetZ = (FP)offset.z; bw.Write(offsetZ.RawValue); //write width bw.Write(editPlane.width); //write height bw.Write(editPlane.height); //write size bw.Write(editPlane.gridsize); int [] gridInfo = editPlane.GetGridInfo(); int len = gridInfo.Length; BitArray bitarray = new BitArray(len); int byteCount = (len + 7) / 8; byte[] data = new byte[byteCount]; for (int i = 0; i < editPlane.height; ++i) { for (int j = 0; j < editPlane.width; ++j) { int index = i * editPlane.width + j; if (gridInfo[i * editPlane.width + j] == 0) { bitarray.Set(index, false); } else { bitarray.Set(index, true); } } } //要写的数据源 bitarray.CopyTo(data, 0); for (int i = 0; i < data.Length; ++i) { bw.Write(data[i]); } bw.Flush(); bw.Close(); fs.Close(); } if (GUILayout.Button("Export", GUILayout.Height(40))) { string filepath = EditorUtility.SaveFilePanelInProject("Save Map", "GridInfo", "txt", "OKOK"); LogManager.Log(filepath); string fileName = filepath; //文件名字 StringBuilder sb = new StringBuilder(); //offset sb.Append("type octile").Append("\r\n"); Vector3 offset = editPlane.transform.position; FP x = (FP)offset.x; sb.Append("X ").Append(x.RawValue).Append("\r\n"); FP z = (FP)offset.z; sb.Append("Z ").Append(z.RawValue).Append("\r\n"); sb.Append("width ").Append(editPlane.width).Append("\r\n"); sb.Append("height ").Append(editPlane.height).Append("\r\n"); FP size = (FP)editPlane.gridsize; sb.Append("size ").Append(size.RawValue).Append("\r\n"); sb.Append("map").Append("\r\n"); int [] gridInfo = editPlane.GetGridInfo(); // int len = gridInfo.Length; for (int i = 0; i < editPlane.height; ++i) { for (int j = 0; j < editPlane.width; ++j) { if (gridInfo[i * editPlane.width + j] == 0) { sb.Append('@'); } else { sb.Append('.'); } } sb.Append("\r\n"); } //要写的数据源 EditorUtils.SaveTextFile(filepath, sb.ToString()); } if (GUILayout.Button("Import", GUILayout.Height(40))) { string filepath = EditorUtility.OpenFilePanel("Load map", Application.dataPath, "txt"); if (filepath != null) { StreamReader reader = new StreamReader(filepath, new UTF8Encoding(false)); if (reader != null) { MapGridT myGrid = new MapGridT(); string content = reader.ReadToEnd(); int readPos = 0; List <string> kv = null; while (readPos < content.Length) { string line = EditorUtils.readLine(content, ref readPos); kv = EditorUtils.splitLine(line); if (kv.Count == 0) { continue; } if (kv[0] == "map") { break; } if (kv[0] == "X") { if (kv.Count > 1) { myGrid.X = float.Parse(kv[1]); } } if (kv[0] == "Z") { if (kv.Count > 1) { myGrid.Z = float.Parse(kv[1]); } } if (kv[0] == "width") { if (kv.Count > 1) { myGrid.Width = int.Parse(kv[1]); } } if (kv[0] == "height") { if (kv.Count > 1) { myGrid.Height = int.Parse(kv[1]); } } if (kv[0] == "size") { if (kv.Count > 1) { myGrid.GridSize = float.Parse(kv[1]); } } } if (myGrid.Width == 0 || myGrid.Height == 0) { StringBuilder log = new StringBuilder(); log.Append("invlid width").Append(myGrid.Width).Append("or height").Append(myGrid.Height); LogManager.Log(log.ToString()); return; } editPlane.transform.position = new Vector3((float)myGrid.X, 0f, (float)myGrid.Z); editPlane.width = myGrid.Width; editPlane.height = myGrid.Height; editPlane.gridsize = (float)myGrid.GridSize; editPlane.GenerateMesh(); int[] gridData = editPlane.GetGridInfo(); for (int i = 0; i < myGrid.Height; i++) { string line = EditorUtils.readLine(content, ref readPos); if (line.Length < myGrid.Width + 1) { StringBuilder log = new StringBuilder(); log.Append("line").Append(i).Append("length is less than").Append(myGrid.Width); LogManager.Log(log.ToString()); return; } for (int w = 0; w < myGrid.Width; w++) { if (line[w] == '.') { gridData[i * myGrid.Width + w] = 1; } else { gridData[i * myGrid.Width + w] = 0; } } } } } } if (GUILayout.Button("ImportCollision", GUILayout.Height(40))) { string filepath = EditorUtility.OpenFilePanel("Load collision", Application.dataPath, "bytes"); if (filepath != null) { FileStream fs = new FileStream(filepath, FileMode.Open, FileAccess.Read); if (fs != null) { BinaryReader br = new BinaryReader(fs); MapGridT myGrid = new MapGridT(); //read offset x myGrid.X = br.ReadSingle(); //read offset z myGrid.Z = br.ReadSingle(); //read width myGrid.Width = br.ReadInt32(); //read height myGrid.Height = br.ReadInt32(); //read size myGrid.GridSize = br.ReadSingle(); if (myGrid.Width == 0 || myGrid.Height == 0) { StringBuilder log = new StringBuilder(); log.Append("invlid width").Append(myGrid.Width).Append("or height").Append(myGrid.Height); LogManager.Log(log.ToString()); return; } editPlane.transform.position = new Vector3((float)myGrid.X, 0f, (float)myGrid.Z); editPlane.width = myGrid.Width; editPlane.height = myGrid.Height; editPlane.gridsize = (float)myGrid.GridSize; editPlane.GenerateMesh(); int [] gridInfo = editPlane.GetGridInfo(); int len = gridInfo.Length; int byteCount = (len + 7) / 8; byte[] data = br.ReadBytes(byteCount); BitArray bitarray = new BitArray(data); for (int i = 0; i < myGrid.Height; i++) { for (int w = 0; w < myGrid.Width; w++) { gridInfo[i * myGrid.Width + w] = bitarray.Get(i * myGrid.Width + w) == true ? 1:0; } } } } } if (GUILayout.Button("CreateFromPath", GUILayout.Height(40))) { int walkNum = 0, nonWalkNum = 0; Polygon[] walkables = new Polygon[16]; for (int a = 0; a < walkables.Length; ++a) { walkables[a] = new Polygon(); } Polygon[] nonWalkables = new Polygon[32]; for (int b = 0; b < nonWalkables.Length; ++b) { nonWalkables[b] = new Polygon(); } //get all pathes WaypointManager manager = GameObject.FindObjectOfType <WaypointManager>(); if (manager) { Vector3 offset = editPlane.transform.position; PathManager[] pathes = manager.GetComponentsInChildren <PathManager>(); foreach (PathManager path in pathes) { if (path.walkable) { for (int i = 0; i < path.waypoints.Length; ++i) { Vector3 pos = path.waypoints[i].position; walkables[walkNum].m_Points.Add(new Vector2(pos.x - offset.x, pos.z - offset.z)); } Vector3 firstPos = path.waypoints[0].position; walkables[walkNum].m_Points.Add(new Vector2(firstPos.x - offset.x, firstPos.z - offset.z)); walkNum++; } else { for (int i = 0; i < path.waypoints.Length; ++i) { Vector3 pos = path.waypoints[i].position; nonWalkables[nonWalkNum].m_Points.Add(new Vector2(pos.x - offset.x, pos.z - offset.z)); } Vector3 firstPos = path.waypoints[0].position; nonWalkables[nonWalkNum].m_Points.Add(new Vector2(firstPos.x - offset.x, firstPos.z - offset.z)); nonWalkNum++; } } } int[] gridData = editPlane.GetGridInfo(); for (int i = 0; i < editPlane.height; i++) { for (int w = 0; w < editPlane.width; w++) { bool processed = false; Vector2 pos = new Vector2(w * editPlane.gridsize + editPlane.gridsize * 0.5f, i * editPlane.gridsize + editPlane.gridsize * 0.5f); for (int nonWalkIndex = 0; nonWalkIndex < nonWalkNum; ++nonWalkIndex) { if (PtInPolygon(pos, nonWalkables[nonWalkIndex].m_Points)) { processed = true; gridData[i * editPlane.width + w] = 0; } } if (!processed) { for (int walkIndex = 0; walkIndex < walkNum; ++walkIndex) { if (PtInPolygon(pos, walkables[walkIndex].m_Points)) { processed = true; gridData[i * editPlane.width + w] = 1; } } } } } } EditorGUILayout.Space(); //draw instructions GUILayout.TextArea("Hint:\nPress 'Brush' to begin a new path, then press 'p' " + "on your keyboard to place green points in the SceneView " + "\n\nPress 'Erase' to do the opposite operation."); }