// Returns the connection color public static Color Drag( InteractionManager interaction, Vector2 mousePosition, NodeGUIData nodeGuiData, NodeConnectionOptions connectionOptions ) { dragData.Set(interaction.targetNode); int connectionIndex = connectionOptions.connectionMode == ConnectionMode.Dual ? DeGUIKey.Exclusive.ctrl && DeGUIKey.Extra.space ? 1 : 0 : interaction.targetNodeConnectorAreaIndex; Color color = GetConnectionColor( connectionIndex, interaction.targetNode.connectedNodesIds.Count, nodeGuiData, connectionOptions ); Vector2 attachP = interaction.targetNodeConnectorArea.center; // Pointers Rect pointerFrom = new Rect(attachP.x - 4, attachP.y - 4, 8, 8); Rect pointerTo = new Rect(mousePosition.x - 4, mousePosition.y - 4, 8, 8); using (new DeGUI.ColorScope(null, null, Color.black)) { GUI.DrawTexture(pointerFrom.Expand(4), DeStylePalette.circle); GUI.DrawTexture(pointerTo.Expand(4), DeStylePalette.circle); } using (new DeGUI.ColorScope(null, null, color)) { GUI.DrawTexture(pointerFrom, DeStylePalette.circle); GUI.DrawTexture(pointerTo, DeStylePalette.circle); } // Line Handles.DrawBezier(attachP, mousePosition, attachP, mousePosition, Color.black, null, _LineSize + 2); Handles.DrawBezier(attachP, mousePosition, attachP, mousePosition, color, null, _LineSize + 2); return(color); }
/// <summary> /// Always connects from BottomOrRight side to TopOrLeft side. /// If ALT is pressed shows the delete connection button. /// Called during Repaint or MouseDown/Up. /// Returns TRUE if the connection was deleted using the delete connection button. /// </summary> public static bool Connect( NodeProcess process, int connectionIndex, int fromTotConnections, NodeConnectionOptions fromOptions, IEditorGUINode fromNode, IEditorGUINode toNode ) { _Styles.Init(); NodeGUIData fromGUIData = process.nodeToGUIData[fromNode]; NodeGUIData toGUIData = process.nodeToGUIData[toNode]; bool useSubFromAreas = fromOptions.connectionMode != ConnectionMode.Dual && fromGUIData.connectorAreas != null; Rect fromArea = useSubFromAreas ? fromGUIData.connectorAreas[connectionIndex] : fromGUIData.fullArea; AnchorsData anchorsData = GetAnchors(process, connectionIndex, fromNode, fromArea, toNode, toGUIData.fullArea, fromOptions, useSubFromAreas); Color color = GetConnectionColor(connectionIndex, fromTotConnections, fromGUIData, fromOptions); // Line (shadow + line) Handles.DrawBezier( anchorsData.fromLineP, anchorsData.toLineP, anchorsData.fromTangent, anchorsData.toTangent, _lineShadowColor, null, _LineSize + 2 ); Handles.DrawBezier(anchorsData.fromLineP, anchorsData.toLineP, anchorsData.fromTangent, anchorsData.toTangent, color, null, _LineSize); // Line start square Rect fromSquareR = anchorsData.fromIsSide ? new Rect(anchorsData.fromMarkP.x, anchorsData.fromMarkP.y - FromSquareHeight * 0.5f, FromSquareWidth, FromSquareHeight) : new Rect(anchorsData.fromMarkP.x - FromSquareHeight * 0.5f, anchorsData.fromMarkP.y, FromSquareHeight, FromSquareWidth); using (new DeGUI.ColorScope(null, null, color)) GUI.DrawTexture(fromSquareR, DeStylePalette.whiteSquare); // Arrow Rect arrowR = new Rect( anchorsData.toArrowP.x - DeStylePalette.ico_nodeArrow.width, anchorsData.toArrowP.y - DeStylePalette.ico_nodeArrow.height * 0.5f, DeStylePalette.ico_nodeArrow.width, DeStylePalette.ico_nodeArrow.height ); Matrix4x4 currGUIMatrix = GUI.matrix; if (anchorsData.arrowRequiresRotation) { GUIUtility.RotateAroundPivot(anchorsData.arrowRotationAngle, anchorsData.toArrowP * process.guiScale + process.guiScalePositionDiff); } using (new DeGUI.ColorScope(null, null, color)) GUI.DrawTexture(arrowR, DeStylePalette.ico_nodeArrow); GUI.matrix = currGUIMatrix; // Delete connection button (placed at center of line) if (DeGUIKey.Exclusive.alt) { Vector2 midP = anchorsData.fromTangent + (anchorsData.toTangent - anchorsData.fromTangent) * 0.5f; Vector2 midPAlt = anchorsData.fromLineP + (anchorsData.toLineP - anchorsData.fromLineP) * 0.5f; midP += (midPAlt - midP) * 0.25f; Rect btR = new Rect(midP.x - 5, midP.y - 5, 10, 10); using (new DeGUI.ColorScope(null, null, color)) GUI.DrawTexture(btR.Expand(2), DeStylePalette.circle); using (new DeGUI.ColorScope(null, null, DeGUI.colors.global.red)) { if (GUI.Button(btR, "", _Styles.btDelete)) { return(true); } } GUI.DrawTexture(btR.Contract(2), DeStylePalette.ico_delete); } return(false); }
// When added has a clone ready (used to verify onCloneNodeCallback). // When multiple copies are pasted, new clones are created public void Add(IEditorGUINode node, IEditorGUINode clone, NodeConnectionOptions connectionOptions, Func <IEditorGUINode, IEditorGUINode, bool> onCloneNodeCallback) { _originalNodes.Add(node); _originalIdToCloneId.Add(node.id, clone.id); _originalNodeToConnectionOptions.Add(node, connectionOptions); _originalNodeToGuiData.Add(node, _process.nodeToGUIData[node]); _cloneToOriginalNode.Add(clone, node); _onCloneNodeCallback = onCloneNodeCallback; currClones.Add(clone); EditorGUIUtility.systemCopyBuffer = _copyBufferId; }
void RefreshAnchorsData() { // Debug.Log("<color=#00ff00>REFRESH</color> " + Event.current.type); _nodeToAnchorsData.Clear(); for (int i = 0; i < _process.nodes.Count; ++i) { IEditorGUINode fromNode = _process.nodes[i]; NodeGUIData fromGUIData = _process.nodeToGUIData[fromNode]; NodeConnectionOptions fromOptions = _process.nodeToConnectionOptions[fromNode]; List <string> connections = fromNode.connectedNodesIds; int totConnections = fromNode.connectedNodesIds.Count; AnchorsData[] anchors = null; for (int c = totConnections - 1; c > -1; --c) { string connId = connections[c]; if (string.IsNullOrEmpty(connId)) { continue; // No connection } if (anchors == null) { anchors = new AnchorsData[totConnections]; } IEditorGUINode toNode = _process.idToNode[connId]; NodeGUIData toGUIData = _process.nodeToGUIData[toNode]; // Verify if area between nodes is visible if (!fromGUIData.isVisible && !toGUIData.isVisible) { Rect area = fromGUIData.fullArea.Add(toGUIData.fullArea); if (!_process.AreaIsVisible(area)) { continue; // No visible connection } } bool useSubFromAreas = fromOptions.connectionMode != ConnectionMode.Dual && fromGUIData.connectorAreas != null && (fromOptions.connectionMode != ConnectionMode.NormalPlus || c < totConnections - 1); Rect fromArea = useSubFromAreas ? fromGUIData.connectorAreas[c] : fromGUIData.fullArea; AnchorsData anchorsData = GetAnchorsAllSides( _process, c, fromNode, new RectCache(fromArea), toNode, new RectCache(toGUIData.fullArea), fromOptions, useSubFromAreas ); anchorsData.isSet = true; anchors[c] = anchorsData; } if (anchors != null) { _nodeToAnchorsData.Add(fromNode, anchors); } } }
// Returns the connection color public Color Drag( InteractionManager interaction, Vector2 mousePosition, NodeGUIData nodeGuiData, NodeConnectionOptions connectionOptions, float lineThickness ) { dragData.Set(interaction.targetNode); int connectionIndex; switch (connectionOptions.connectionMode) { case ConnectionMode.Dual: connectionIndex = DeGUIKey.Exclusive.ctrl && DeGUIKey.Extra.space ? 1 : 0; break; case ConnectionMode.NormalPlus: connectionIndex = DeGUIKey.Exclusive.ctrl && DeGUIKey.Extra.space ? interaction.targetNode.connectedNodesIds.Count - 1 : interaction.targetNodeConnectorAreaIndex; break; default: connectionIndex = interaction.targetNodeConnectorAreaIndex; break; } Color color = GetConnectionColor( connectionIndex, interaction.targetNode.connectedNodesIds.Count, nodeGuiData, connectionOptions ); Vector2 attachP = interaction.targetNodeConnectorArea.center; // Pointers Rect pointerFrom = new Rect(attachP.x - 4, attachP.y - 4, 8, 8); Rect pointerTo = new Rect(mousePosition.x - 4, mousePosition.y - 4, 8, 8); using (new DeGUI.ColorScope(null, null, Color.black)) { GUI.DrawTexture(pointerFrom.Expand(4), DeStylePalette.circle); GUI.DrawTexture(pointerTo.Expand(4), DeStylePalette.circle); } using (new DeGUI.ColorScope(null, null, color)) { GUI.DrawTexture(pointerFrom, DeStylePalette.circle); GUI.DrawTexture(pointerTo, DeStylePalette.circle); } // Line Handles.DrawBezier(attachP, mousePosition, attachP, mousePosition, Color.black, null, lineThickness + 2); Handles.DrawBezier(attachP, mousePosition, attachP, mousePosition, color, null, lineThickness); return(color); }
static Color GetConnectionColor(int connectionIndex, int totConnections, NodeGUIData nodeGuiData, NodeConnectionOptions connectionOptions) { if (connectionOptions.connectionMode == ConnectionMode.NormalPlus) { if (connectionIndex == totConnections - 1 || connectionOptions.gradientColor == null) { // PLUS connection return(connectionOptions.startColor == Color.clear ? nodeGuiData.mainColor : connectionOptions.startColor); } else { // Regular return(connectionOptions.gradientColor.Evaluate(connectionIndex / (float)(totConnections - 2))); } } return(totConnections < 2 || connectionOptions.gradientColor == null ? connectionOptions.startColor == Color.clear ? nodeGuiData.mainColor : connectionOptions.startColor : connectionOptions.gradientColor.Evaluate(connectionIndex / (float)(totConnections - 1))); }
/// <summary> /// Always connects from BottomOrRight side to TopOrLeft side. /// If ALT is pressed shows the delete connection button. /// Called during Repaint or MouseDown/Up. /// Returns TRUE if the connection was deleted using the delete connection button. /// </summary> public bool Connect( int connectionIndex, int fromTotConnections, NodeConnectionOptions fromOptions, IEditorGUINode fromNode ) { _Styles.Init(); if (_anchorsDataRefreshRequired) { _anchorsDataRefreshRequired = false; RefreshAnchorsData(); } NodeGUIData fromGUIData = _process.nodeToGUIData[fromNode]; if (!_nodeToAnchorsData.ContainsKey(fromNode)) { return(false); } AnchorsData anchorsData = _nodeToAnchorsData[fromNode][connectionIndex]; if (!anchorsData.isSet) { return(false); } // Color color = GetConnectionColor(connectionIndex, fromTotConnections, fromGUIData, fromOptions); // Line (shadow + line) if (_process.options.connectorsShadow) { Handles.DrawBezier( anchorsData.fromLineP, anchorsData.toLineP, anchorsData.fromTangent, anchorsData.toTangent, _LineShadowColor, null, _process.options.connectorsThickness + 2 ); } Handles.DrawBezier(anchorsData.fromLineP, anchorsData.toLineP, anchorsData.fromTangent, anchorsData.toTangent, color, null, _process.options.connectorsThickness); // Line start square Rect fromSquareR; switch (anchorsData.fromSide) { case ConnectionSide.Top: fromSquareR = new Rect(anchorsData.fromMarkP.x - _FromSquareHeight * 0.5f, anchorsData.fromMarkP.y - _FromSquareWidth, _FromSquareHeight, _FromSquareWidth); break; case ConnectionSide.Bottom: fromSquareR = new Rect(anchorsData.fromMarkP.x - _FromSquareHeight * 0.5f, anchorsData.fromMarkP.y, _FromSquareHeight, _FromSquareWidth); break; case ConnectionSide.Left: fromSquareR = new Rect(anchorsData.fromMarkP.x - _FromSquareWidth, anchorsData.fromMarkP.y - _FromSquareHeight * 0.5f, _FromSquareWidth, _FromSquareHeight); break; default: // Right fromSquareR = new Rect(anchorsData.fromMarkP.x, anchorsData.fromMarkP.y - _FromSquareHeight * 0.5f, _FromSquareWidth, _FromSquareHeight); break; } using (new DeGUI.ColorScope(null, null, color)) GUI.DrawTexture(fromSquareR, DeStylePalette.whiteSquare); // Arrow Rect arrowR = new Rect( anchorsData.toArrowP.x - DeStylePalette.ico_nodeArrow.width, anchorsData.toArrowP.y - DeStylePalette.ico_nodeArrow.height * 0.5f, DeStylePalette.ico_nodeArrow.width, DeStylePalette.ico_nodeArrow.height ); Matrix4x4 currGUIMatrix = GUI.matrix; if (anchorsData.arrowRequiresRotation) { GUIUtility.RotateAroundPivot(anchorsData.arrowRotationAngle, anchorsData.toArrowP * _process.guiScale + _process.guiScalePositionDiff); } using (new DeGUI.ColorScope(null, null, color)) GUI.DrawTexture(arrowR, DeStylePalette.ico_nodeArrow); GUI.matrix = currGUIMatrix; // Delete connection button (placed at center of line) if (DeGUIKey.Exclusive.alt) { Vector2 midP = anchorsData.fromTangent + (anchorsData.toTangent - anchorsData.fromTangent) * 0.5f; Vector2 midPAlt = anchorsData.fromLineP + (anchorsData.toLineP - anchorsData.fromLineP) * 0.5f; midP += (midPAlt - midP) * 0.25f; Rect btR = new Rect(midP.x - 5, midP.y - 5, 10, 10); using (new DeGUI.ColorScope(null, null, color)) GUI.DrawTexture(btR.Expand(2), DeStylePalette.circle); using (new DeGUI.ColorScope(null, null, DeGUI.colors.global.red)) { if (GUI.Button(btR, "", _Styles.btDelete)) { return(true); } } GUI.DrawTexture(btR.Contract(2), DeStylePalette.ico_delete); } return(false); }
static AnchorsData GetAnchors_2Sides( NodeProcess process, int connectionIndex, IEditorGUINode fromNode, Rect fromArea, IEditorGUINode toNode, Rect toArea, NodeConnectionOptions connectionOptions, bool sideOnly ) { AnchorsData a = new AnchorsData(); float distX = toArea.x - fromArea.xMax; float distY = toArea.y - fromArea.yMax; bool fromIsBottom = !sideOnly && fromArea.yMax < toArea.y && distY >= distX && FromAnchorCanBeBottom(process, fromNode, fromArea, toNode, toArea); a.fromMarkP = fromIsBottom ? new Vector2(fromArea.center.x, fromArea.yMax) : new Vector2(fromArea.xMax, fromArea.center.y); if (connectionOptions.connectionMode == ConnectionMode.Dual) { if (fromIsBottom) { a.fromMarkP.x += connectionIndex == 1 ? 4 : -4; } else { a.fromMarkP.y += connectionIndex == 1 ? 4 : -4; } } // Find correct fromLineP a.fromLineP = a.fromMarkP; if (fromIsBottom) { a.fromLineP.y += _FromSquareWidth; } else { a.fromLineP.x += _FromSquareWidth; } // bool toIsTop = toArea.y > a.fromMarkP.y && (fromArea.xMax > toArea.x || toArea.y - a.fromMarkP.y > toArea.center.x - a.fromMarkP.x) && ToAnchorCanBeTop(process, fromNode, fromArea, toNode, toArea); a.toArrowP = a.toLineP = toIsTop ? new Vector2(toArea.center.x, toArea.y) : new Vector2(toArea.x, toArea.center.y); a.fromIsSide = !fromIsBottom; a.toIsSide = !toIsTop; // Set tangents bool isToBehindFrom = a.toArrowP.x < a.fromMarkP.x && a.toArrowP.y < fromArea.yMax; float dist = Vector2.Distance(a.toArrowP, a.fromLineP); a.isStraight = connectionOptions.connectorMode == ConnectorMode.Straight || !isToBehindFrom && connectionOptions.connectorMode == ConnectorMode.Smart && dist <= _MaxDistanceForSmartStraight; if (a.isStraight) { a.fromTangent = a.fromLineP; a.toTangent = a.toArrowP; } else { if (toIsTop) { a.toLineP.y -= DeStylePalette.ico_nodeArrow.width; } else { a.toLineP.x -= DeStylePalette.ico_nodeArrow.width; } float axisDistance = a.fromIsSide ? Mathf.Abs(a.toArrowP.x - a.fromLineP.x) : Mathf.Abs(a.toArrowP.y - a.fromLineP.y); float tangentDistance = isToBehindFrom ? _TangentDistanceIfInverse : Mathf.Min(_TangentDistance, axisDistance * 0.2f + dist * 0.2f); a.fromTangent = a.fromLineP + (fromIsBottom ? Vector2.up * tangentDistance : Vector2.right * tangentDistance); a.toTangent = a.toLineP + (toIsTop? Vector2.up * -tangentDistance : Vector2.right * -tangentDistance); } // Set arrow if (a.isStraight) { a.arrowRequiresRotation = true; a.arrowRotationAngle = -AngleBetween(Vector2.right, a.toArrowP - a.fromLineP); } else if (toIsTop) { a.arrowRequiresRotation = true; a.arrowRotationAngle = 90; } return(a); }
static AnchorsData GetAnchorsAllSides( NodeProcess process, int connectionIndex, IEditorGUINode fromNode, RectCache fromArea, IEditorGUINode toNode, RectCache toArea, NodeConnectionOptions connectionOptions, bool sideOnly ) { AnchorsData a = new AnchorsData(); // From/to side bool toSideSetByFrom = false; if (sideOnly) { a.fromSide = ConnectionSide.Right; } else { if (toArea.x >= fromArea.x) { // R/T/B if (toArea.x < fromArea.xMax) { if (FromAnchorCanBeVertical(process, fromNode, fromArea, toNode, toArea)) { a.fromSide = toArea.center.y < fromArea.center.y ? ConnectionSide.Top : ConnectionSide.Bottom; } else { bool nearVertSnapOffset = toArea.y > fromArea.yMax && fromArea.yMax - toArea.y <= NodeProcess.SnapOffset; bool rightToTop = nearVertSnapOffset && fromArea.xMax < toArea.center.x; bool leftToTop = !rightToTop && fromArea.x > toArea.center.x; if (rightToTop) { a.fromSide = ConnectionSide.Right; a.toSide = ConnectionSide.Top; } else if (leftToTop) { a.fromSide = ConnectionSide.Left; a.toSide = ConnectionSide.Top; } else { a.fromSide = ConnectionSide.Left; a.toSide = ConnectionSide.Left; } toSideSetByFrom = true; } } else { if (toArea.yMax > fromArea.y && toArea.y < fromArea.yMax) { a.fromSide = ConnectionSide.Right; } else { float dX = toArea.x - fromArea.xMax; float dY = toArea.center.y < fromArea.y ? toArea.center.y - fromArea.y : toArea.center.y - fromArea.yMax; if (dX > Mathf.Abs(dY) || !FromAnchorCanBeVertical(process, fromNode, fromArea, toNode, toArea)) { a.fromSide = ConnectionSide.Right; } else { a.fromSide = dY < 0 ? ConnectionSide.Top : ConnectionSide.Bottom; } } } } else { // L/T/B if (toArea.xMax > fromArea.x) { if (FromAnchorCanBeVertical(process, fromNode, fromArea, toNode, toArea)) { a.fromSide = toArea.center.y < fromArea.center.y ? ConnectionSide.Top : ConnectionSide.Bottom; } else { a.fromSide = ConnectionSide.Right; a.toSide = ConnectionSide.Right; toSideSetByFrom = true; } } else { if (toArea.yMax > fromArea.y && toArea.y < fromArea.yMax) { a.fromSide = ConnectionSide.Left; } else { float dX = fromArea.x - toArea.xMax; float dY = toArea.yMax < fromArea.y ? toArea.yMax - fromArea.y : toArea.y - fromArea.yMax; if (dX > Mathf.Abs(dY) || !FromAnchorCanBeVertical(process, fromNode, fromArea, toNode, toArea)) { a.fromSide = ConnectionSide.Left; } else { a.fromSide = dY < 0 ? ConnectionSide.Top : ConnectionSide.Bottom; } } } } } // To side if (!toSideSetByFrom) { a.toSide = ConnectionSide.Left; switch (a.fromSide) { case ConnectionSide.Top: a.toSide = ToAnchorCanBeVertical(process, fromNode, fromArea, a.fromSide, toNode, toArea) ? ConnectionSide.Bottom : toArea.center.x < fromArea.center.x ? ConnectionSide.Right : ConnectionSide.Left; break; case ConnectionSide.Bottom: a.toSide = ToAnchorCanBeVertical(process, fromNode, fromArea, a.fromSide, toNode, toArea) ? ConnectionSide.Top : toArea.center.x < fromArea.center.x ? ConnectionSide.Right : ConnectionSide.Left; break; case ConnectionSide.Left: a.toSide = ConnectionSide.Right; break; default: // Right if (sideOnly && toArea.x < fromArea.xMax) { // Right side was forced, see if we can connect to sweeter sides a.toSide = toArea.center.x >= fromArea.xMax ? toArea.yMax < fromArea.y ? ConnectionSide.Bottom : ConnectionSide.Top : ConnectionSide.Right; } else { a.toSide = ConnectionSide.Left; } break; } } // a.fromIsSide = a.fromSide == ConnectionSide.Left || a.fromSide == ConnectionSide.Right; a.toIsSide = a.toSide == ConnectionSide.Left || a.toSide == ConnectionSide.Right; // int fromDisplacement = sideOnly ? 0 : 8; switch (a.fromSide) { case ConnectionSide.Top: a.fromLineP = a.fromMarkP = new Vector2(fromArea.center.x + fromDisplacement, fromArea.y); a.fromLineP.y -= _FromSquareWidth; if (connectionOptions.connectionMode == ConnectionMode.Dual) { a.fromLineP.x = a.fromMarkP.x += connectionIndex == 1 ? 4 : -4; } break; case ConnectionSide.Bottom: a.fromLineP = a.fromMarkP = new Vector2(fromArea.center.x + fromDisplacement, fromArea.yMax); a.fromLineP.y += _FromSquareWidth; if (connectionOptions.connectionMode == ConnectionMode.Dual) { a.fromLineP.x = a.fromMarkP.x += connectionIndex == 1 ? 4 : -4; } break; case ConnectionSide.Left: a.fromLineP = a.fromMarkP = new Vector2(fromArea.x, fromArea.center.y + fromDisplacement); a.fromLineP.x -= _FromSquareWidth; if (connectionOptions.connectionMode == ConnectionMode.Dual) { a.fromLineP.y = a.fromMarkP.y += connectionIndex == 1 ? 4 : -4; } break; case ConnectionSide.Right: a.fromLineP = a.fromMarkP = new Vector2(fromArea.xMax, fromArea.center.y + fromDisplacement); a.fromLineP.x += _FromSquareWidth; if (connectionOptions.connectionMode == ConnectionMode.Dual) { a.fromLineP.y = a.fromMarkP.y += connectionIndex == 1 ? 4 : -4; } break; } const float maxDistForDirect = 20; switch (a.toSide) { case ConnectionSide.Top: a.toArrowP = a.toLineP = new Vector2(toArea.center.x, toArea.y); if (Vector2.Distance(a.fromLineP, a.toLineP) < maxDistForDirect) { a.toArrowP.x = a.toLineP.x += fromDisplacement; } break; case ConnectionSide.Bottom: a.toArrowP = a.toLineP = new Vector2(toArea.center.x, toArea.yMax); if (Vector2.Distance(a.fromLineP, a.toLineP) < maxDistForDirect) { a.toArrowP.x = a.toLineP.x += fromDisplacement; } break; case ConnectionSide.Left: a.toArrowP = a.toLineP = new Vector2(toArea.x, toArea.center.y); if (Vector2.Distance(a.fromLineP, a.toLineP) < maxDistForDirect) { a.toArrowP.y = a.toLineP.y += fromDisplacement; } break; case ConnectionSide.Right: a.toArrowP = a.toLineP = new Vector2(toArea.xMax, toArea.center.y); if (Vector2.Distance(a.fromLineP, a.toLineP) < maxDistForDirect) { a.toArrowP.y = a.toLineP.y += fromDisplacement; } break; } // Set tangents + arrows // bool toIsBehindFrom = a.fromSide == ConnectionSide.Right && a.toArrowP.x < a.fromMarkP.x && a.toArrowP.y < fromArea.yMax; bool toIsBehindFrom = a.fromSide == ConnectionSide.Right && a.toArrowP.x < fromArea.center.x; float d = Vector2.Distance(a.toArrowP, a.fromLineP); a.isStraight = connectionOptions.connectorMode == ConnectorMode.Straight || !toIsBehindFrom && connectionOptions.connectorMode == ConnectorMode.Smart && d <= _MaxDistanceForSmartStraight || Mathf.Approximately(a.toLineP.x, a.fromLineP.x) || Mathf.Approximately(a.toLineP.y, a.fromLineP.y); if (a.isStraight) { a.fromTangent = a.fromLineP; a.toTangent = a.toArrowP; a.arrowRequiresRotation = true; a.arrowRotationAngle = -AngleBetween(Vector2.right, a.toArrowP - a.fromLineP); } else { float axisDistance = a.fromIsSide ? Mathf.Abs(a.toArrowP.x - a.fromLineP.x) : Mathf.Abs(a.toArrowP.y - a.fromLineP.y); float tangentDistance = toIsBehindFrom ? _TangentDistanceIfInverse : Mathf.Min(_TangentDistance, axisDistance * 0.2f + d * 0.2f); Vector2 fromTangentOffset, toTangentOffset; switch (a.fromSide) { case ConnectionSide.Top: fromTangentOffset = Vector2.up * -tangentDistance; break; case ConnectionSide.Bottom: fromTangentOffset = Vector2.up * tangentDistance; break; case ConnectionSide.Left: fromTangentOffset = Vector2.right * -tangentDistance; break; default: // Right fromTangentOffset = Vector2.right * tangentDistance; break; } switch (a.toSide) { case ConnectionSide.Top: a.toLineP.y -= DeStylePalette.ico_nodeArrow.width; toTangentOffset = Vector2.up * -tangentDistance; a.arrowRequiresRotation = true; a.arrowRotationAngle = 90; break; case ConnectionSide.Bottom: a.toLineP.y += DeStylePalette.ico_nodeArrow.width; toTangentOffset = Vector2.up * tangentDistance; a.arrowRequiresRotation = true; a.arrowRotationAngle = -90; break; case ConnectionSide.Left: a.toLineP.x -= DeStylePalette.ico_nodeArrow.width; toTangentOffset = Vector2.right * -tangentDistance; break; default: // Right a.toLineP.x += DeStylePalette.ico_nodeArrow.width; toTangentOffset = Vector2.right * tangentDistance; a.arrowRequiresRotation = true; a.arrowRotationAngle = 180; break; } a.fromTangent = a.fromLineP + fromTangentOffset; a.toTangent = a.toLineP + toTangentOffset; } return(a); }
static Color GetConnectionColor(int connectionIndex, int totConnections, NodeGUIData nodeGuiData, NodeConnectionOptions connectionOptions) { return(totConnections < 2 || connectionOptions.gradientColor == null ? connectionOptions.startColor == Color.clear ? nodeGuiData.mainColor : connectionOptions.startColor : connectionOptions.gradientColor.Evaluate(connectionIndex / (float)(totConnections - 1))); }
/// <summary> /// Returns a list of pasteable nodes, with their GUID recreated and their connections adapted /// </summary> /// <returns></returns> public List <T> GetNodesToPaste <T>() where T : IEditorGUINode, new() { if (_originalNodes.Count == 0) { return(null); } List <T> result = new List <T>(); if (_requiresRecloningOnNextPaste) { // Create new clones currClones.Clear(); _originalIdToCloneId.Clear(); _cloneToOriginalNode.Clear(); foreach (IEditorGUINode original in _originalNodes) { T clone = CloneNode <T>(original); if (_onCloneNodeCallback != null && !_onCloneNodeCallback(original, clone)) { continue; } _cloneToOriginalNode.Add(clone, original); _originalIdToCloneId[original.id] = clone.id; currClones.Add(clone); result.Add(clone); } } else { foreach (IEditorGUINode clone in currClones) { result.Add((T)clone); } } // Replace all interconnected ids with new ones, and eliminate others foreach (IEditorGUINode original in _originalNodes) { NodeConnectionOptions connectionOptions = _originalNodeToConnectionOptions[original]; IEditorGUINode clone = GetCloneByOriginalId(original.id); for (int c = clone.connectedNodesIds.Count - 1; c > -1; --c) { string connectionId = clone.connectedNodesIds[c]; if (IsConnectionToCopiedNode(connectionId)) { // Replace connection ID with clone's ID clone.connectedNodesIds[c] = _originalIdToCloneId[connectionId]; } else { // Clear or delete connection switch (connectionOptions.connectionMode) { case ConnectionMode.Flexible: clone.connectedNodesIds.RemoveAt(c); break; default: clone.connectedNodesIds[c] = null; break; } } } } _requiresRecloningOnNextPaste = true; return(result); }