/// <summary> Draw a connection as we are dragging it </summary> public void DrawDraggedConnection() { if (IsDraggingPort) { Gradient gradient = graphEditor.GetNoodleGradient(draggedOutput, null); float thickness = graphEditor.GetNoodleThickness(draggedOutput, null); NoodlePath path = graphEditor.GetNoodlePath(draggedOutput, null); NoodleStroke stroke = graphEditor.GetNoodleStroke(draggedOutput, null); Rect fromRect; if (!_portConnectionPoints.TryGetValue(draggedOutput, out fromRect)) { return; } List <Vector2> gridPoints = new List <Vector2>(); gridPoints.Add(fromRect.center); for (int i = 0; i < draggedOutputReroutes.Count; i++) { gridPoints.Add(draggedOutputReroutes[i]); } if (draggedOutputTarget != null) { gridPoints.Add(portConnectionPoints[draggedOutputTarget].center); } else { gridPoints.Add(WindowToGridPosition(Event.current.mousePosition)); } DrawNoodle(gradient, path, stroke, thickness, gridPoints); GUIStyle portStyle = NodeEditorWindow.current.graphEditor.GetPortStyle(draggedOutput); Color bgcol = Color.black; Color frcol = gradient.colorKeys[0].color; bgcol.a = 0.6f; frcol.a = 0.6f; // Loop through reroute points again and draw the points for (int i = 0; i < draggedOutputReroutes.Count; i++) { // Draw reroute point at position Rect rect = new Rect(draggedOutputReroutes[i], new Vector2(16, 16)); rect.position = new Vector2(rect.position.x - 8, rect.position.y - 8); rect = GridToWindowRect(rect); NodeEditorGUILayout.DrawPortHandle(rect, bgcol, frcol, portStyle.normal.background, portStyle.active.background); } } }
/// <summary> Draws all connections </summary> public void DrawConnections() { Vector2 mousePos = Event.current.mousePosition; List <RerouteReference> selection = preBoxSelectionReroute != null ? new List <RerouteReference>(preBoxSelectionReroute) : new List <RerouteReference>(); hoveredReroute = new RerouteReference(); List <Vector2> gridPoints = new List <Vector2>(2); Color col = GUI.color; foreach (XNode.Node node in graph.nodes) { //If a null node is found, return. This can happen if the nodes associated script is deleted. It is currently not possible in Unity to delete a null asset. if (node == null) { continue; } // Draw full connections and output > reroute foreach (XNode.NodePort output in node.Outputs) { //Needs cleanup. Null checks are ugly Rect fromRect; if (!_portConnectionPoints.TryGetValue(output, out fromRect)) { continue; } Color portColor = graphEditor.GetPortColor(output); for (int k = 0; k < output.ConnectionCount; k++) { XNode.NodePort input = output.GetConnection(k); Gradient noodleGradient = graphEditor.GetNoodleGradient(output, input); float noodleThickness = graphEditor.GetNoodleThickness(output, input); NoodlePath noodlePath = graphEditor.GetNoodlePath(output, input); NoodleStroke noodleStroke = graphEditor.GetNoodleStroke(output, input); // Error handling if (input == null) { continue; //If a script has been updated and the port doesn't exist, it is removed and null is returned. If this happens, return. } if (!input.IsConnectedTo(output)) { input.Connect(output); } Rect toRect; if (!_portConnectionPoints.TryGetValue(input, out toRect)) { continue; } List <Vector2> reroutePoints = output.GetReroutePoints(k); gridPoints.Clear(); gridPoints.Add(fromRect.center); gridPoints.AddRange(reroutePoints); gridPoints.Add(toRect.center); float tempT = noodleThickness; if (output.ValueType.ToString() == "BehaviorNode") { tempT *= 1.25f; } DrawNoodle(noodleGradient, noodlePath, noodleStroke, tempT, gridPoints); // Loop through reroute points again and draw the points for (int i = 0; i < reroutePoints.Count; i++) { RerouteReference rerouteRef = new RerouteReference(output, k, i); // Draw reroute point at position Rect rect = new Rect(reroutePoints[i], new Vector2(12, 12)); rect.position = new Vector2(rect.position.x - 6, rect.position.y - 6); rect = GridToWindowRect(rect); // Draw selected reroute points with an outline if (selectedReroutes.Contains(rerouteRef)) { GUI.color = NodeEditorPreferences.GetSettings().highlightColor; GUI.DrawTexture(rect, NodeEditorResources.dotOuter); } GUI.color = portColor; GUI.DrawTexture(rect, NodeEditorResources.dot); if (rect.Overlaps(selectionBox)) { selection.Add(rerouteRef); } if (rect.Contains(mousePos)) { hoveredReroute = rerouteRef; } } } } } GUI.color = col; if (Event.current.type != EventType.Layout && currentActivity == NodeActivity.DragGrid) { selectedReroutes = selection; } }
/// <summary> Draw a bezier from output to input in grid coordinates </summary> public void DrawNoodle(Gradient gradient, NoodlePath path, NoodleStroke stroke, float thickness, List <Vector2> gridPoints) { // convert grid points to window points for (int i = 0; i < gridPoints.Count; ++i) { gridPoints[i] = GridToWindowPosition(gridPoints[i]); } Handles.color = gradient.Evaluate(0f); int length = gridPoints.Count; switch (path) { case NoodlePath.Curvy: Vector2 outputTangent = Vector2.right; for (int i = 0; i < length - 1; i++) { Vector2 inputTangent; // Cached most variables that repeat themselves here to avoid so many indexer calls :p Vector2 point_a = gridPoints[i]; Vector2 point_b = gridPoints[i + 1]; float dist_ab = Vector2.Distance(point_a, point_b); if (i == 0) { outputTangent = zoom * dist_ab * 0.01f * Vector2.right; } if (i < length - 2) { Vector2 point_c = gridPoints[i + 2]; Vector2 ab = (point_b - point_a).normalized; Vector2 cb = (point_b - point_c).normalized; Vector2 ac = (point_c - point_a).normalized; Vector2 p = (ab + cb) * 0.5f; float tangentLength = (dist_ab + Vector2.Distance(point_b, point_c)) * 0.005f * zoom; float side = ((ac.x * (point_b.y - point_a.y)) - (ac.y * (point_b.x - point_a.x))); p = tangentLength * Mathf.Sign(side) * new Vector2(-p.y, p.x); inputTangent = p; } else { inputTangent = zoom * dist_ab * 0.01f * Vector2.left; } // Calculates the tangents for the bezier's curves. float zoomCoef = 50 / zoom; Vector2 tangent_a = point_a + outputTangent * zoomCoef; Vector2 tangent_b = point_b + inputTangent * zoomCoef; // Hover effect. int division = Mathf.RoundToInt(.2f * dist_ab) + 3; //here // Coloring and bezier drawing. int draw = 0; Vector2 bezierPrevious = point_a; for (int j = 1; j <= division; ++j) { if (stroke == NoodleStroke.Dashed) { draw++; if (draw >= 2) { draw = -2; } if (draw < 0) { continue; } if (draw == 0) { bezierPrevious = CalculateBezierPoint(point_a, tangent_a, tangent_b, point_b, (j - 1f) / (float)division); } } if (i == length - 2) { Handles.color = gradient.Evaluate((j + 1f) / division); } Vector2 bezierNext = CalculateBezierPoint(point_a, tangent_a, tangent_b, point_b, j / (float)division); DrawAAPolyLineNonAlloc(thickness, bezierPrevious, bezierNext); bezierPrevious = bezierNext; } outputTangent = -inputTangent; } break; case NoodlePath.Straight: for (int i = 0; i < length - 1; i++) { Vector2 point_a = gridPoints[i]; Vector2 point_b = gridPoints[i + 1]; // Draws the line with the coloring. Vector2 prev_point = point_a; // Approximately one segment per 5 pixels int segments = (int)Vector2.Distance(point_a, point_b) / 5; segments = Math.Max(segments, 1); int draw = 0; for (int j = 0; j <= segments; j++) { draw++; float t = j / (float)segments; Vector2 lerp = Vector2.Lerp(point_a, point_b, t); if (draw > 0) { if (i == length - 2) { Handles.color = gradient.Evaluate(t); } DrawAAPolyLineNonAlloc(thickness, prev_point, lerp); } prev_point = lerp; if (stroke == NoodleStroke.Dashed && draw >= 2) { draw = -2; } } } break; case NoodlePath.Angled: for (int i = 0; i < length - 1; i++) { if (i == length - 1) { continue; // Skip last index } if (gridPoints[i].x <= gridPoints[i + 1].x - (50 / zoom)) { float midpoint = (gridPoints[i].x + gridPoints[i + 1].x) * 0.5f; Vector2 start_1 = gridPoints[i]; Vector2 end_1 = gridPoints[i + 1]; start_1.x = midpoint; end_1.x = midpoint; if (i == length - 2) { DrawAAPolyLineNonAlloc(thickness, gridPoints[i], start_1); Handles.color = gradient.Evaluate(0.5f); DrawAAPolyLineNonAlloc(thickness, start_1, end_1); Handles.color = gradient.Evaluate(1f); DrawAAPolyLineNonAlloc(thickness, end_1, gridPoints[i + 1]); } else { DrawAAPolyLineNonAlloc(thickness, gridPoints[i], start_1); DrawAAPolyLineNonAlloc(thickness, start_1, end_1); DrawAAPolyLineNonAlloc(thickness, end_1, gridPoints[i + 1]); } } else { float midpoint = (gridPoints[i].y + gridPoints[i + 1].y) * 0.5f; Vector2 start_1 = gridPoints[i]; Vector2 end_1 = gridPoints[i + 1]; start_1.x += 25 / zoom; end_1.x -= 25 / zoom; Vector2 start_2 = start_1; Vector2 end_2 = end_1; start_2.y = midpoint; end_2.y = midpoint; if (i == length - 2) { DrawAAPolyLineNonAlloc(thickness, gridPoints[i], start_1); Handles.color = gradient.Evaluate(0.25f); DrawAAPolyLineNonAlloc(thickness, start_1, start_2); Handles.color = gradient.Evaluate(0.5f); DrawAAPolyLineNonAlloc(thickness, start_2, end_2); Handles.color = gradient.Evaluate(0.75f); DrawAAPolyLineNonAlloc(thickness, end_2, end_1); Handles.color = gradient.Evaluate(1f); DrawAAPolyLineNonAlloc(thickness, end_1, gridPoints[i + 1]); } else { DrawAAPolyLineNonAlloc(thickness, gridPoints[i], start_1); DrawAAPolyLineNonAlloc(thickness, start_1, start_2); DrawAAPolyLineNonAlloc(thickness, start_2, end_2); DrawAAPolyLineNonAlloc(thickness, end_2, end_1); DrawAAPolyLineNonAlloc(thickness, end_1, gridPoints[i + 1]); } } } break; case NoodlePath.ShaderLab: Vector2 start = gridPoints[0]; Vector2 end = gridPoints[length - 1]; //Modify first and last point in array so we can loop trough them nicely. gridPoints[0] = gridPoints[0] + Vector2.right * (20 / zoom); gridPoints[length - 1] = gridPoints[length - 1] + Vector2.left * (20 / zoom); //Draw first vertical lines going out from nodes Handles.color = gradient.Evaluate(0f); //DrawAAPolyLineNonAlloc(thickness, start, gridPoints[0]); Vector2 midPoint = ((gridPoints[0] + Vector2.right * (5 / zoom)) + (gridPoints[length - 1] + Vector2.left * (5 / zoom))) / 2; Vector2 startBez = CalculateBezierPoint(gridPoints[0], midPoint, gridPoints[0] + Vector2.right * (25 / zoom), (gridPoints[0] + midPoint) / 2f, .1f); Vector3 endBez = CalculateBezierPoint(gridPoints[length - 1], midPoint, gridPoints[length - 1] + Vector2.left * (25 / zoom), (gridPoints[length - 1] + midPoint) / 2f, .1f); //draw the bendy parts Handles.DrawBezier((gridPoints[0] + start) / 2, startBez, new Vector2(((gridPoints[0].x + startBez.x) / 2 + gridPoints[0].x) / 2, gridPoints[0].y), gridPoints[0], gradient.Evaluate(0f), null, thickness); //2nd bendy Handles.DrawBezier((gridPoints[length - 1] + end) / 2, endBez, new Vector2(((gridPoints[length - 1].x + endBez.x) / 2 + gridPoints[length - 1].x) / 2, gridPoints[length - 1].y), gridPoints[length - 1], gradient.Evaluate(0f), null, thickness); //Handles.DrawBezier(end,endBez,gridPoints[length-1]+Vector2.left*(25/zoom),gridPoints[length-1]+Vector2.left*(20/zoom),gradient.Evaluate(0f),null,thickness); //draw the middle Handles.DrawBezier(startBez, endBez, startBez, endBez, gradient.Evaluate(0f), null, thickness); //draw the roots Handles.DrawBezier(start, (gridPoints[0] + start) / 2, start, (gridPoints[0] + start) / 2, gradient.Evaluate(0f), null, thickness); Handles.DrawBezier(end, (gridPoints[length - 1] + end) / 2, end, (gridPoints[length - 1] + end) / 2, gradient.Evaluate(0f), null, thickness); //Handles.color = gradient.Evaluate(1f); //DrawAAPolyLineNonAlloc(thickness, end, gridPoints[length - 1]); //Handles.DrawBezier(gridPoints[0],gridPoints[length-1],gridPoints[0]+Vector2.right*(20/zoom),gridPoints[length-1]+Vector2.left*(20/zoom),gradient.Evaluate(0f),null,thickness); /* * for (int i = 0; i < length - 1; i++) { * Vector2 point_a = gridPoints[i]; * Vector2 point_b = gridPoints[i + 1]; * // Draws the line with the coloring. * Vector2 prev_point = point_a; * // Approximately one segment per 5 pixels * int segments = (int) Vector2.Distance(point_a, point_b) / 5; * segments = Math.Max(segments, 1); * * int draw = 0; * for (int j = 0; j <= segments; j++) { * draw++; * float t = j / (float) segments; * Vector2 lerp = Vector2.Lerp(point_a, point_b, t); * if (draw > 0) { * if (i == length - 2) Handles.color = gradient.Evaluate(t); * DrawAAPolyLineNonAlloc(thickness, prev_point, lerp); * } * prev_point = lerp; * if (stroke == NoodleStroke.Dashed && draw >= 1) draw = -1; * } * }*/ gridPoints[0] = start; gridPoints[length - 1] = end; break; } }
public void DrawLinks() { Vector2 mousePos = Event.current.mousePosition; List <RerouteReference> selection = preBoxSelectionReroute != null ? new List <RerouteReference>(preBoxSelectionReroute) : new List <RerouteReference>(); hoveredReroute = new RerouteReference(); List <Vector2> gridPoints = new List <Vector2>(2); Color col = GUI.color; foreach (XNode.Node node in graph.nodes) { //If a null node is found, return. This can happen if the nodes associated script is deleted. It is currently not possible in Unity to delete a null asset. if (node == null) { continue; } var links = XNode.NodeDataCache.GetOutputLinks(node.GetType()).Select(x => new NodeLinkPort(node, x)); // Draw full connections and output > reroute foreach (var output in links) { //Needs cleanup. Null checks are ugly Rect fromRect; if (!linkConnectionPoints.TryGetValue(output, out fromRect)) { continue; } Color portColor = graphEditor.GetLinkColor(output.Item2); List <NodeLink> connections = output.GetConnections(); for (int k = 0; k < connections.Count; k++) { NodeLink link = connections[k]; if (!link) { Debug.LogWarning("There was a null entry in a node's connected links list. Removing."); output.VerifyConnections(); connections.RemoveAt(k); k--; continue; } NodeLinkPort input = link.GetToPort(); Gradient noodleGradient = graphEditor.GetNoodleGradient(output, input); float noodleThickness = graphEditor.GetNoodleThickness(link); NoodlePath noodlePath = graphEditor.GetNoodlePath(output, input); NoodleStroke noodleStroke = graphEditor.GetNoodleStroke(output, input); // Error handling if (input == null) { continue; //If a script has been updated and the port doesn't exist, it is removed and null is returned. If this happens, return. } //if (!input.IsConnectedTo(output)) input.Connect(output); Rect toRect; if (!linkConnectionPoints.TryGetValue(input, out toRect)) { continue; } List <Vector2> reroutePoints = link.reroutePoints; gridPoints.Clear(); gridPoints.Add(fromRect.center); gridPoints.AddRange(reroutePoints); gridPoints.Add(toRect.center); DrawNoodle(noodleGradient, noodlePath, noodleStroke, noodleThickness, gridPoints, link); // Loop through reroute points again and draw the points for (int i = 0; i < reroutePoints.Count; i++) { //RerouteReference rerouteRef = new RerouteReference(output, k, i); // Draw reroute point at position Rect rect = new Rect(reroutePoints[i], new Vector2(12, 12)); rect.position = new Vector2(rect.position.x - 6, rect.position.y - 6); rect = GridToWindowRect(rect); // TODO: //// Draw selected reroute points with an outline //if (selectedReroutes.Contains(rerouteRef)) { // GUI.color = NodeEditorPreferences.GetSettings().highlightColor; // GUI.DrawTexture(rect, NodeEditorResources.dotOuter); //} GUI.color = portColor; GUI.DrawTexture(rect, NodeEditorResources.dot); //if (rect.Overlaps(selectionBox)) selection.Add(rerouteRef); //if (rect.Contains(mousePos)) hoveredReroute = rerouteRef; } } } GUI.color = col; if (Event.current.type != EventType.Layout && currentActivity == NodeActivity.DragGrid) { selectedReroutes = selection; } } }
/// <summary> Draw a bezier from output to input in grid coordinates </summary> public void DrawNoodle(Gradient gradient, NoodlePath path, NoodleStroke stroke, float thickness, List <Vector2> gridPoints, UnityEngine.Object select = null) { // convert grid points to window points for (int i = 0; i < gridPoints.Count; ++i) { gridPoints[i] = GridToWindowPosition(gridPoints[i]); } Handles.color = gradient.Evaluate(0f); int length = gridPoints.Count; switch (path) { case NoodlePath.Curvy: Vector2 outputTangent = Vector2.right; for (int i = 0; i < length - 1; i++) { Vector2 inputTangent; // Cached most variables that repeat themselves here to avoid so many indexer calls :p Vector2 point_a = gridPoints[i]; Vector2 point_b = gridPoints[i + 1]; float dist_ab = Vector2.Distance(point_a, point_b); if (i == 0) { outputTangent = zoom * dist_ab * 0.01f * Vector2.right; } if (i < length - 2) { Vector2 point_c = gridPoints[i + 2]; Vector2 ab = (point_b - point_a).normalized; Vector2 cb = (point_b - point_c).normalized; Vector2 ac = (point_c - point_a).normalized; Vector2 p = (ab + cb) * 0.5f; float tangentLength = (dist_ab + Vector2.Distance(point_b, point_c)) * 0.005f * zoom; float side = ((ac.x * (point_b.y - point_a.y)) - (ac.y * (point_b.x - point_a.x))); p = tangentLength * Mathf.Sign(side) * new Vector2(-p.y, p.x); inputTangent = p; } else { inputTangent = zoom * dist_ab * 0.01f * Vector2.left; } // Calculates the tangents for the bezier's curves. float zoomCoef = 50 / zoom; Vector2 tangent_a = point_a + outputTangent * zoomCoef; Vector2 tangent_b = point_b + inputTangent * zoomCoef; // Hover effect. int division = Mathf.RoundToInt(.2f * dist_ab) + 3; // Coloring and bezier drawing. int draw = 0; Vector2 bezierPrevious = point_a; for (int j = 1; j <= division; ++j) { if (stroke == NoodleStroke.Dashed) { draw++; if (draw >= 2) { draw = -2; } if (draw < 0) { continue; } if (draw == 0) { bezierPrevious = CalculateBezierPoint(point_a, tangent_a, tangent_b, point_b, (j - 1f) / (float)division); } } if (i == length - 2) { Handles.color = gradient.Evaluate((j + 1f) / division); } Vector2 bezierNext = CalculateBezierPoint(point_a, tangent_a, tangent_b, point_b, j / (float)division); DrawAAPolyLineNonAlloc(thickness, bezierPrevious, bezierNext, select); bezierPrevious = bezierNext; } outputTangent = -inputTangent; } break; case NoodlePath.Straight: for (int i = 0; i < length - 1; i++) { Vector2 point_a = gridPoints[i]; Vector2 point_b = gridPoints[i + 1]; // Draws the line with the coloring. Vector2 prev_point = point_a; // Approximately one segment per 5 pixels int segments = (int)Vector2.Distance(point_a, point_b) / 5; int draw = 0; for (int j = 0; j <= segments; j++) { draw++; float t = j / (float)segments; Vector2 lerp = Vector2.Lerp(point_a, point_b, t); if (draw > 0) { if (i == length - 2) { Handles.color = gradient.Evaluate(t); } DrawAAPolyLineNonAlloc(thickness, prev_point, lerp, select); } prev_point = lerp; if (stroke == NoodleStroke.Dashed && draw >= 2) { draw = -2; } } } break; case NoodlePath.Angled: for (int i = 0; i < length - 1; i++) { if (i == length - 1) { continue; // Skip last index } if (gridPoints[i].x <= gridPoints[i + 1].x - (50 / zoom)) { float midpoint = (gridPoints[i].x + gridPoints[i + 1].x) * 0.5f; Vector2 start_1 = gridPoints[i]; Vector2 end_1 = gridPoints[i + 1]; start_1.x = midpoint; end_1.x = midpoint; if (i == length - 2) { DrawAAPolyLineNonAlloc(thickness, gridPoints[i], start_1, select); Handles.color = gradient.Evaluate(0.5f); DrawAAPolyLineNonAlloc(thickness, start_1, end_1, select); Handles.color = gradient.Evaluate(1f); DrawAAPolyLineNonAlloc(thickness, end_1, gridPoints[i + 1], select); } else { DrawAAPolyLineNonAlloc(thickness, gridPoints[i], start_1, select); DrawAAPolyLineNonAlloc(thickness, start_1, end_1, select); DrawAAPolyLineNonAlloc(thickness, end_1, gridPoints[i + 1], select); } } else { float midpoint = (gridPoints[i].y + gridPoints[i + 1].y) * 0.5f; Vector2 start_1 = gridPoints[i]; Vector2 end_1 = gridPoints[i + 1]; start_1.x += 25 / zoom; end_1.x -= 25 / zoom; Vector2 start_2 = start_1; Vector2 end_2 = end_1; start_2.y = midpoint; end_2.y = midpoint; if (i == length - 2) { DrawAAPolyLineNonAlloc(thickness, gridPoints[i], start_1, select); Handles.color = gradient.Evaluate(0.25f); DrawAAPolyLineNonAlloc(thickness, start_1, start_2, select); Handles.color = gradient.Evaluate(0.5f); DrawAAPolyLineNonAlloc(thickness, start_2, end_2, select); Handles.color = gradient.Evaluate(0.75f); DrawAAPolyLineNonAlloc(thickness, end_2, end_1, select); Handles.color = gradient.Evaluate(1f); DrawAAPolyLineNonAlloc(thickness, end_1, gridPoints[i + 1], select); } else { DrawAAPolyLineNonAlloc(thickness, gridPoints[i], start_1, select); DrawAAPolyLineNonAlloc(thickness, start_1, start_2, select); DrawAAPolyLineNonAlloc(thickness, start_2, end_2, select); DrawAAPolyLineNonAlloc(thickness, end_2, end_1, select); DrawAAPolyLineNonAlloc(thickness, end_1, gridPoints[i + 1], select); } } } break; } }
/// <summary> Draw a bezier from output to input in grid coordinates </summary> public void DrawNoodle(Gradient gradient, NoodlePath path, NoodleStroke stroke, float thickness, List <Vector2> gridPoints) { Vector2[] windowPoints = gridPoints.Select(x => GridToWindowPosition(x)).ToArray(); Handles.color = gradient.Evaluate(0f); int length = gridPoints.Count; switch (path) { case NoodlePath.Curvy: Vector2 outputTangent = Vector2.right; for (int i = 0; i < length - 1; i++) { Vector2 inputTangent = Vector2.left; // Cached most variables that repeat themselves here to avoid so many indexer calls :p Vector2 point_a = windowPoints[i]; Vector2 point_b = windowPoints[i + 1]; float dist_ab = Vector2.Distance(point_a, point_b); if (i == 0) { outputTangent = Vector2.right * dist_ab * 0.01f * zoom; } if (i < length - 2) { Vector2 point_c = windowPoints[i + 2]; Vector2 ab = (point_b - point_a).normalized; Vector2 cb = (point_b - point_c).normalized; Vector2 ac = (point_c - point_a).normalized; Vector2 p = (ab + cb) * 0.5f; float tangentLength = (dist_ab + Vector2.Distance(point_b, point_c)) * 0.005f * zoom; float side = ((ac.x * (point_b.y - point_a.y)) - (ac.y * (point_b.x - point_a.x))); p = new Vector2(-p.y, p.x) * Mathf.Sign(side) * tangentLength; inputTangent = p; } else { inputTangent = Vector2.left * dist_ab * 0.01f * zoom; } // Calculates the tangents for the bezier's curves. Vector2 tangent_a = point_a + outputTangent * 50 / zoom; Vector2 tangent_b = point_b + inputTangent * 50 / zoom; // Hover effect. int division = Mathf.RoundToInt(.2f * dist_ab) + 3; Vector3[] points = Handles.MakeBezierPoints(point_a, point_b, tangent_a, tangent_b, division); int draw = 0; // Coloring and bezier drawing. for (int j = 0; j < points.Length - 1; j++) { if (stroke == NoodleStroke.Dashed) { draw++; if (draw >= 2) { draw = -2; } if (draw < 0) { continue; } } if (i == gridPoints.Count - 2) { Handles.color = gradient.Evaluate((j + 1f) / points.Length); } Handles.DrawAAPolyLine(thickness, points[j], points[j + 1]); } outputTangent = -inputTangent; } break; case NoodlePath.Straight: for (int i = 0; i < length - 1; i++) { Vector2 point_a = windowPoints[i]; Vector2 point_b = windowPoints[i + 1]; // Draws the line with the coloring. Vector2 prev_point = point_a; // Approximately one segment per 5 pixels int segments = (int)Vector2.Distance(point_a, point_b) / 5; int draw = 0; for (int j = 0; j <= segments; j++) { draw++; float t = j / (float)segments; Vector2 lerp = Vector2.Lerp(point_a, point_b, t); if (draw > 0) { if (i == gridPoints.Count - 2) { Handles.color = gradient.Evaluate(t); } Handles.DrawAAPolyLine(thickness, prev_point, lerp); } prev_point = lerp; if (stroke == NoodleStroke.Dashed && draw >= 2) { draw = -2; } } } break; case NoodlePath.Angled: for (int i = 0; i < length - 1; i++) { if (i == length - 1) { continue; // Skip last index } if (windowPoints[i].x <= windowPoints[i + 1].x - (50 / zoom)) { float midpoint = (windowPoints[i].x + windowPoints[i + 1].x) * 0.5f; Vector2 start_1 = windowPoints[i]; Vector2 end_1 = windowPoints[i + 1]; start_1.x = midpoint; end_1.x = midpoint; if (i == gridPoints.Count - 2) { Handles.DrawAAPolyLine(thickness, windowPoints[i], start_1); Handles.color = gradient.Evaluate(0.5f); Handles.DrawAAPolyLine(thickness, start_1, end_1); Handles.color = gradient.Evaluate(1f); Handles.DrawAAPolyLine(thickness, end_1, windowPoints[i + 1]); } else { Handles.DrawAAPolyLine(thickness, windowPoints[i], start_1); Handles.DrawAAPolyLine(thickness, start_1, end_1); Handles.DrawAAPolyLine(thickness, end_1, windowPoints[i + 1]); } } else { float midpoint = (windowPoints[i].y + windowPoints[i + 1].y) * 0.5f; Vector2 start_1 = windowPoints[i]; Vector2 end_1 = windowPoints[i + 1]; start_1.x += 25 / zoom; end_1.x -= 25 / zoom; Vector2 start_2 = start_1; Vector2 end_2 = end_1; start_2.y = midpoint; end_2.y = midpoint; if (i == gridPoints.Count - 2) { Handles.DrawAAPolyLine(thickness, windowPoints[i], start_1); Handles.color = gradient.Evaluate(0.25f); Handles.DrawAAPolyLine(thickness, start_1, start_2); Handles.color = gradient.Evaluate(0.5f); Handles.DrawAAPolyLine(thickness, start_2, end_2); Handles.color = gradient.Evaluate(0.75f); Handles.DrawAAPolyLine(thickness, end_2, end_1); Handles.color = gradient.Evaluate(1f); Handles.DrawAAPolyLine(thickness, end_1, windowPoints[i + 1]); } else { Handles.DrawAAPolyLine(thickness, windowPoints[i], start_1); Handles.DrawAAPolyLine(thickness, start_1, start_2); Handles.DrawAAPolyLine(thickness, start_2, end_2); Handles.DrawAAPolyLine(thickness, end_2, end_1); Handles.DrawAAPolyLine(thickness, end_1, windowPoints[i + 1]); } } } break; } }
private static void DrawNoodleLabesPositions(List <Vector2> gridPoints, Node node, NodePort port) { NoodlePath path = NodeEditorPreferences.GetSettings().noodlePath; NoodleStroke stroke = NodeEditorPreferences.GetSettings().noodleStroke; float zoom = NodeEditorWindow.current.zoom; // convert grid points to window points for (int i = 0; i < gridPoints.Count; ++i) { gridPoints[i] = NodeEditorWindow.current.GridToWindowPosition(gridPoints[i]); } int length = gridPoints.Count; Vector2 point_a = Vector2.zero; Vector2 point_b = Vector2.zero; Vector2 labelPosition = Vector2.zero; switch (path) { case NoodlePath.Curvy: if (length > 2) { labelPosition = gridPoints[length / 2]; } else { point_a = gridPoints[0]; point_b = gridPoints[1]; labelPosition = (point_a + point_b) / 2; } break; case NoodlePath.Straight: case NoodlePath.Angled: case NoodlePath.ShaderLab: if (length > 2) { if (length % 2 == 0) { point_a = gridPoints[length / 2]; point_b = gridPoints[(length / 2) - 1]; labelPosition = (point_a + point_b) / 2; } else { labelPosition = gridPoints[length / 2]; } } else { point_a = gridPoints[0]; point_b = gridPoints[1]; labelPosition = (point_a + point_b) / 2; } break; } GUIContent content = new GUIContent(((INodeNoodleLabel)node).GetNoodleLabel(port)); Vector2 size = EditorStyles.helpBox.CalcSize(content); labelPosition.y -= size.y / 2; labelPosition.x -= (size.x / 2); TextAnchor textAnchor = EditorStyles.helpBox.alignment; FontStyle fontStype = EditorStyles.helpBox.fontStyle; GUI.backgroundColor = new Color(0, 0, 0, 255); GUI.color = new Color(255, 255, 255, 255); EditorStyles.helpBox.alignment = TextAnchor.MiddleCenter; EditorStyles.helpBox.fontStyle = FontStyle.BoldAndItalic; Handles.Label(labelPosition, content, EditorStyles.helpBox); EditorStyles.helpBox.fontStyle = fontStype; EditorStyles.helpBox.alignment = textAnchor; GUI.color = Color.white; GUI.backgroundColor = Color.white; }