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