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; } //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); //checkbox field for drawing waypoint direction rotation 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); //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(); } //update use of child transforms as waypoints if (GUILayout.Button("Update Path from Children")) { Undo.RecordObject(script, "Update Waypoints"); script.Create(); SceneView.RepaintAll(); } 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; } } //orient waypoints to the path in forward direction if (GUILayout.Button("Rotate Waypoints To Path")) { Undo.RecordObject(script, "Rotate Waypoints"); for (int i = 0; i < script.bPoints.Count; i++) { //save child rotations before applying waypoint rotation Vector3[] globalPos = new Vector3[script.bPoints[i].wp.childCount]; for (int j = 0; j < globalPos.Length; j++) { globalPos[j] = script.bPoints[i].wp.GetChild(j).position; } if (i == script.bPoints.Count - 1) { script.bPoints[i].wp.rotation = script.bPoints[i - 1].wp.rotation; } else { script.bPoints[i].wp.LookAt(script.bPoints[i + 1].wp); } //restore previous location after rotation for (int j = 0; j < globalPos.Length; j++) { script.bPoints[i].wp.GetChild(j).position = globalPos[j]; } } } 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() { //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); } }