void DrawLine(BezierPathNode start, BezierPathNode end) { var a = start.transform.position; var b = start.NextDir.position; var c = end.LastDir.position; var d = end.transform.position; DrawBezierPath(a, b, c, d, 4, start.transform); }
/// <summary> /// Draws all nodes that are siblings of the specified <paramref name="node"/>. /// </summary> /// <param name="node">The node whose siblings to render.</param> public void DrawAllNodesFrom([NotNull] BezierPathNode node) { var path = node.transform.parent.GetComponent <BezierPath>(); if (path == null) { return; } DrawAllNodes(path, node); }
/// <summary> /// Draw all nodes in a specified <paramref name="path"/>. /// </summary> /// <param name="path">The path to render child nodes from.</param> /// <param name="selectedNode"> /// The node that is considered to be active (e.g., selected) in the specified path; /// if <see langword="null"/>, no node is highlighted. /// </param> public void DrawAllNodes([NotNull] BezierPath path, [CanBeNull] BezierPathNode selectedNode = null) { var transform = path.transform; var closedPath = path.Closed; var nodes = GetNodeList(transform); var lastNodeIndex = nodes.Count - 1; for (var i = 0; i < nodes.Count; ++i) { var currentNode = nodes[i]; var nextNode = DetermineNextNode(i); var drawIncoming = i > 0 || closedPath; var drawOutgoing = i < lastNodeIndex || closedPath; var isActive = currentNode == selectedNode; // Make sure Gizmos/Handle coordinates are local to the parent. using (new Handles.DrawingScope(Handles.matrix)) { // Connect waypoints var shouldDrawConnection = i < lastNodeIndex || (nodes.Count > 2); if (nextNode != null && shouldDrawConnection) { using (new Handles.DrawingScope(Color.gray)) { Handles.DrawDottedLine(currentNode.Center, nextNode.Center, DashedLineWidth); } } // Connect current outgoing control with next incoming control. if (nextNode != null) { using (new Handles.DrawingScope(Color.magenta)) { Handles.DrawDottedLine( currentNode.Out + currentNode.Center, nextNode.In + nextNode.Center, DottedLineWidth); } } // Draw the actual handles. DrawNodeSceneGui(transform, currentNode, isActive, drawIncoming, drawOutgoing); } } BezierPathNode DetermineNextNode(int i) => i < lastNodeIndex ? nodes[i + 1] : closedPath ? nodes[0] : null; }
private void Awake() { _node = (BezierPathNode)target; }
/// <summary> /// Draws the Scene GUI for a specific node. /// </summary> /// <param name="parentPath">The transform of the owning <see cref="BezierPath"/>.</param> /// <param name="node">The node to render.</param> /// <param name="isActive">Whether the node to be rendered is considered to be active, i.e. by selection.</param> /// <param name="drawIncoming">Whether the incoming connection should be rendered, e.g. for the first node.</param> /// <param name="drawOutgoing">Whether the outgoing connection should be rendered, e.g. for the last node.</param> public void DrawNodeSceneGui([NotNull] Transform parentPath, [NotNull] BezierPathNode node, bool isActive, bool drawIncoming, bool drawOutgoing) { using (new Handles.DrawingScope(Handles.matrix)) { var transform = node.transform; var size = HandleUtility.GetHandleSize(transform.position); var snap = Vector3.up * 0.1f; var positionCap = isActive ? (Handles.CapFunction)Handles.CubeHandleCap : Handles.RectangleHandleCap; var controlCap = isActive ? (Handles.CapFunction)Handles.SphereHandleCap : Handles.CircleHandleCap; var positionCapSize = size * (isActive ? 0.125f : 0.0625f); var controlCapSize = size * (isActive ? 0.125f : 0.0625f); // Handles.matrix = parentPath.localToWorldMatrix; // Draw position handle // TODO: We may want to allow a rotation control here anyways. using (new Handles.DrawingScope(Color.gray)) { EditorGUI.BeginChangeCheck(); var nodePosition = Handles.FreeMoveHandle(node.Center, Quaternion.identity, positionCapSize, snap, positionCap); if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(node, "Position of waypoint"); node.Center = nodePosition; // TODO: Selection.activeGameObject = node.gameObject; } } // Make sure Gizmos/Handle coordinates are local to the parent. using (new Handles.DrawingScope(Handles.matrix * transform.localToWorldMatrix)) { // Draw incoming control handle. Unconnected paths don't need an initial incoming control. if (drawIncoming) { using (new Handles.DrawingScope(Color.blue)) { Handles.DrawLine(Vector3.zero, node.In); EditorGUI.BeginChangeCheck(); var handlePos = Handles.FreeMoveHandle(node.In, Quaternion.identity, controlCapSize, snap, controlCap); if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(node, "Position of control"); node.In = handlePos; // TODO: Selection.activeGameObject = node.gameObject; } } } // Draw outgoing control handle. Unconnected paths don't need a final outgoing control. if (drawOutgoing) { using (new Handles.DrawingScope(Color.red)) { Handles.DrawLine(Vector3.zero, node.Out); EditorGUI.BeginChangeCheck(); var handlePos = Handles.FreeMoveHandle(node.Out, Quaternion.identity, controlCapSize, snap, controlCap); if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(node, "Position of control"); node.Out = handlePos; // TODO: Selection.activeGameObject = node.gameObject; } } } } } }