public ConnectionLineView(PortEditorView portViewA, PortEditorView portViewB, GraphEditorData graphEditorData) { if (portViewA.FlowType == portViewB.FlowType) { Debug.LogError("两个端口的FlowType相同,无法连接"); return; } this.graphEditorData = graphEditorData; this.FlowOutPortView = portViewA.FlowType == FlowType.In ? portViewB : portViewA; this.FlowInPortView = portViewB.FlowType == FlowType.In ? portViewB : portViewA; //流入节点都只允许一个连接 graphEditorData.ClearPortAllConnections(FlowInPortView); if (!FlowOutPortView.connectedPortList.Contains(FlowInPortView)) { FlowOutPortView.connectedPortList.Add(FlowInPortView); } if (!FlowInPortView.connectedPortList.Contains(FlowOutPortView)) { FlowInPortView.connectedPortList.Add(FlowOutPortView); } }
void OpenAddNodeWindow(object mousePositionObject) { Vector2 mousePosition = (Vector2)mousePositionObject; try { PopupWindow.Show(new Rect(mousePosition + position.position, new Vector2(200, 0)), new AddNodePopupWindow(type => { if (data.CheckDuplicateEntranceNode(type)) { EditorUtility.DisplayDialog("重复入口类型", "每一种入口节点只允许存在一个", "ok"); return; } //重置tip显示 currentHoverNodeView = null; currentHoverPortView = null; startHoverdTime = EditorApplication.timeSinceStartup; int newId = data.GetNewNodeId(); NodeReflectionInfo reflectionInfo = new NodeReflectionInfo(type); NodeEditorView nodeEditorView = new NodeEditorView(WindowPositionToGraphPosition(mousePosition), this, newId, reflectionInfo); data.CurrentNodeList.Add(nodeEditorView); })); } catch { } }
public void DeleteNode(NodeEditorView nodeView) { if (nodeView == null) { return; } if (!nodeList.Contains(nodeView)) { return; } List <PortEditorView> allPortList = nodeView.allPortList; for (int i = 0; i < allPortList.Count; i++) { PortEditorView portView = allPortList[i]; ClearPortAllConnections(portView); } nodeList.Remove(nodeView); if (CurrentNodeList.Contains(nodeView)) { CurrentNodeList.Remove(nodeView); } }
public void DeleteConnectionLine(ConnectionLineView connectionLineView) { if (connectionLineView == null) { return; } if (!connectionLineList.Contains(connectionLineView)) { return; } PortEditorView flowOutPort = connectionLineView.FlowOutPortView; PortEditorView flowInport = connectionLineView.FlowInPortView; if (flowOutPort.connectedPortList.Contains(flowInport)) { flowOutPort.connectedPortList.Remove(flowInport); } if (flowInport.connectedPortList.Contains(flowOutPort)) { flowInport.connectedPortList.Remove(flowOutPort); } connectionLineList.Remove(connectionLineView); if (CurrentConnectionLineList.Contains(connectionLineView)) { CurrentConnectionLineList.Remove(connectionLineView); } }
void Reset() { if (data != null) { data.Clear(); } draggingNodeView = null; currentHoverPortView = null; currentHoverNodeView = null; controlType = ControlType.None; repaintTimer = EditorApplication.timeSinceStartup; }
/// <summary> /// 检查两个端口是否可以连接 /// </summary> /// <param name="portA"></param> /// <param name="portB"></param> /// <returns></returns> public static bool CheckPortsCanLine(PortEditorView portA, PortEditorView portB) { if (portA == null || portB == null) { return(false); } if (portA.FlowType == portB.FlowType) { return(false); } if (portA.NodeView == portB.NodeView) { return(false); } PortEditorView flowOutPortView = portA.FlowType == FlowType.Out ? portA : portB; PortEditorView flowInPortView = portA.FlowType == FlowType.In ? portA : portB; //两边接口是流出和流入 if (flowOutPortView is FlowOutPortEditorView && flowInPortView is FlowInPortEditorView) { return(true); } //两边接口是Output和Input OutputPortEditorView outputPortView = flowOutPortView as OutputPortEditorView; InputPortEditorView inputPortView = flowInPortView as InputPortEditorView; if (outputPortView == null || inputPortView == null) { Debug.LogError("端口连接类型错误"); return(false); } if (outputPortView.PortValueType != inputPortView.PortValueType) { return(false); } //存取技能变量的端口,都不允许连接 if (inputPortView.inputPortReflectionInfo.inputValueType == typeof(VariableWrapper)) { return(false); } return(true); }
private static Offset <NodeFlowOutPortInfo> ConvertToRuntimeFlowOutPortInfo(FlatBufferBuilder fbb, FlowOutPortEditorView flowOutPort) { List <PortEditorView> connectionPortList = flowOutPort.connectedPortList; int connectionPortCount = connectionPortList.Count; NodeFlowOutPortInfo.StartTargetNodeIdsVector(fbb, connectionPortCount); for (int i = connectionPortCount - 1; i >= 0; i--) { PortEditorView targetPortView = connectionPortList[i]; fbb.AddInt(targetPortView.NodeView.NodeId); } VectorOffset offset = fbb.EndVector(); NodeFlowOutPortInfo.StartNodeFlowOutPortInfo(fbb); NodeFlowOutPortInfo.AddTargetNodeIds(fbb, offset); return(NodeFlowOutPortInfo.EndNodeFlowOutPortInfo(fbb)); }
void CalculateNodeSize() { float nodeNameWidth = Utility.GetStringGuiWidth(ReflectionInfo.NodeName + "(0) ", Utility.GetGuiStyle("NodeName").fontSize); //width float leftMaxWidth = 0f, rightMaxWidth = 0f; int leftPortCount = 0; int rightPortCount = 0; for (int i = 0; i < allPortList.Count(); i++) { PortEditorView portView = allPortList[i]; float width = portView.GetNameWidth(); if (portView.FlowType == FlowType.In) { leftPortCount++; if (width > leftMaxWidth) { leftMaxWidth = width; } } else { rightPortCount++; if (width > rightMaxWidth) { rightMaxWidth = width; } } } viewRect.width = Mathf.Max(leftMaxWidth + rightMaxWidth + PortAreaPadding, nodeNameWidth); viewRect.height = NodeNameRect.height + PortAreaPadding + Mathf.Max( PortLayoutHelper.CalculateHeightByPortCount(leftPortCount), PortLayoutHelper.CalculateHeightByPortCount(rightPortCount)); leftPortLayoutHelper.SetOffset(0, leftMaxWidth); rightPortLayoutHelper.SetOffset(viewRect.width - rightMaxWidth, rightMaxWidth); //中间留点padding }
public void ClearPortAllConnections(PortEditorView portView) { if (portView == null) { return; } List <PortEditorView> connectedPortList = portView.connectedPortList; for (int i = 0; i < connectedPortList.Count; i++) { PortEditorView connectedPort = connectedPortList[i]; if (connectedPort.connectedPortList.Contains(portView)) { connectedPort.connectedPortList.Remove(portView); FindConnectionByPortsAndRemoveIt(portView, connectedPort); } } portView.connectedPortList.Clear(); }
public void FindConnectionByPortsAndRemoveIt(PortEditorView portA, PortEditorView portB) { if (portA == null || portB == null) { return; } if (portA.FlowType == portB.FlowType) { Debug.LogError("RemoveConnectionByPort err: 两个接口类型相同"); return; } PortEditorView flowInPort = portA.FlowType == FlowType.In ? portA : portB; PortEditorView flowOutPort = portA.FlowType == FlowType.Out ? portA : portB; ConnectionLineView needRemoveConnectionLineView = null; for (int i = 0; i < connectionLineList.Count; i++) { ConnectionLineView connectionLineView = connectionLineList[i]; if (connectionLineView.FlowInPortView == flowInPort && connectionLineView.FlowOutPortView == flowOutPort) { needRemoveConnectionLineView = connectionLineView; break; } } if (needRemoveConnectionLineView != null) { connectionLineList.Remove(needRemoveConnectionLineView); if (CurrentConnectionLineList.Contains(needRemoveConnectionLineView)) { CurrentConnectionLineList.Remove(needRemoveConnectionLineView); } } }
void ProcessEvent(Event e) { Vector2 windowMousePosition = e.mousePosition; Vector2 zoomedMousePosition = NonZoomedWindowPositionToZoomedWindowPosition(windowMousePosition); List <NodeEditorView> nodeViewList = data.CurrentNodeList; List <ConnectionLineView> connectionLineViewList = data.CurrentConnectionLineList; bool hasHoveredNodeOrPort = false; //如果在输入标签上,要屏蔽与注释框的交互 bool hasHoverdNodeInputLabel = false; for (int i = 0; i < nodeViewList.Count; i++) { NodeEditorView nodeView = nodeViewList[i]; #region 提示框鼠标悬浮显示 //在没有任何操作的时候,才显示tips框 if (controlType == ControlType.None && !hasHoveredNodeOrPort) { if (nodeView.NodeNameRect.Contains(zoomedMousePosition)) { //reset time if (currentHoverNodeView != nodeView) { startHoverdTime = EditorApplication.timeSinceStartup; } hasHoveredNodeOrPort = true; currentHoverNodeView = nodeView; currentHoverPortView = null; } if (!hasHoveredNodeOrPort) { List <PortEditorView> allPortList = nodeView.allPortList; for (int j = 0; j < allPortList.Count; j++) { PortEditorView portView = allPortList[j]; if (portView.portViewRect.Contains(zoomedMousePosition)) { //reset time if (currentHoverPortView != portView) { startHoverdTime = EditorApplication.timeSinceStartup; } hasHoveredNodeOrPort = true; currentHoverPortView = portView; currentHoverNodeView = null; break; } if (portView is InputPortEditorView) { InputPortEditorView inputView = portView as InputPortEditorView; if (inputView.IsInputLabelContains(zoomedMousePosition)) { hasHoverdNodeInputLabel = true; } } } } } #endregion if (controlType == ControlType.None && e.type == EventType.MouseDown && e.button == 0) { //点击开始拖拽连线 List <PortEditorView> allPortList = nodeView.allPortList; for (int j = 0; j < allPortList.Count; j++) { PortEditorView portView = allPortList[j]; if (portView.connectionCircleRect.Contains(zoomedMousePosition)) { controlType = ControlType.DraggingConnection; draggingLineView = new ConnectionLineView(portView); draggingLineView.SetEndPos(zoomedMousePosition); e.Use(); break; } } //开始拖拽节点 if (nodeView.viewRect.Contains(zoomedMousePosition)) { if (data.selectedNodeList.Contains(nodeView)) { controlType = ControlType.DraggingMultiNodes; } else { controlType = ControlType.DraggingNode; draggingNodeView = nodeView; data.PutNodeToListTail(i); } e.Use(); break; } } //节点右键菜单 if (controlType == ControlType.None && e.type == EventType.MouseDown && e.button == 1) { if (nodeView.viewRect.Contains(zoomedMousePosition)) { OpenNodeGenericMenu(nodeView, e.mousePosition); e.Use(); break; } } } if (currentHoverConnectionLineView != null) { currentHoverConnectionLineView.SetHovering(false); } currentHoverConnectionLineView = null; if (controlType == ControlType.None) { //和连接线的交互 for (int i = 0; i < connectionLineViewList.Count; i++) { ConnectionLineView connectionLineView = connectionLineViewList[i]; if (connectionLineView.IsPositionCloseToLine(zoomedMousePosition)) { currentHoverConnectionLineView = connectionLineView; currentHoverConnectionLineView.SetHovering(true); //右键点击连线 if (e.type == EventType.MouseDown && e.button == 1) { OpenConnectionLineGenericMenu(connectionLineView, e.mousePosition); e.Use(); } break; } } } if (!hasHoveredNodeOrPort) { currentHoverPortView = null; currentHoverNodeView = null; } if (controlType == ControlType.DraggingNode && e.type == EventType.MouseDrag && e.button == 0) { draggingNodeView.Drag(e.delta / data.GraphZoom); e.Use(); } if (controlType == ControlType.DraggingNode && e.type == EventType.MouseUp && e.button == 0) { controlType = ControlType.None; draggingNodeView = null; e.Use(); } if (controlType == ControlType.DraggingMultiNodes && e.type == EventType.MouseDrag && e.button == 0) { for (int i = 0; i < data.selectedNodeList.Count; i++) { data.selectedNodeList[i].Drag(e.delta / data.GraphZoom); } e.Use(); } if (controlType == ControlType.DraggingMultiNodes && e.type == EventType.MouseUp && e.button == 0) { controlType = ControlType.None; e.Use(); } if (controlType == ControlType.DraggingConnection && e.type == EventType.MouseDrag && e.button == 0) { if (draggingLineView != null) { draggingLineView.SetEndPos(zoomedMousePosition); } } if (controlType == ControlType.DraggingConnection && e.type == EventType.MouseUp && e.button == 0) { if (draggingLineView != null) { bool createNewConnection = false; //检查是否有连接 for (int i = 0; i < nodeViewList.Count; i++) { NodeEditorView nodeView = nodeViewList[i]; List <PortEditorView> allPortList = nodeView.allPortList; for (int j = 0; j < allPortList.Count; j++) { PortEditorView portView = allPortList[j]; if (portView.connectionCircleRect.Contains(zoomedMousePosition)) { if (ConnectionLineView.CheckPortsCanLine(draggingLineView.draggingPort, portView)) { ConnectionLineView newConnectionLine = new ConnectionLineView(draggingLineView.draggingPort, portView, data); data.connectionLineList.Add(newConnectionLine); data.CurrentConnectionLineList.Add(newConnectionLine); createNewConnection = true; break; } } } if (createNewConnection) { break; } } draggingLineView.Dispose(); } draggingLineView = null; controlType = ControlType.None; e.Use(); } //中键拖动面板 if (e.type == EventType.MouseDrag && e.button == 2) { data.GraphOffset += e.delta / data.GraphZoom; e.Use(); if (draggingLineView != null) { draggingLineView.SetEndPos(zoomedMousePosition); } } //滚轮控制缩放 if (e.type == EventType.ScrollWheel) { data.GraphZoom -= e.delta.y / GraphEditorData.GraphZoomSpeed; data.GraphZoom = Mathf.Clamp(data.GraphZoom, GraphEditorData.MinGraphZoom, GraphEditorData.MaxGraphZoom); e.Use(); if (draggingLineView != null) { draggingLineView.SetEndPos(zoomedMousePosition); } } //记录左ctrl按下状态 if (e.type == EventType.KeyDown && e.keyCode == KeyCode.LeftControl) { isCtrlDown = true; } //记录左ctrl按下状态 if (e.type == EventType.KeyUp && e.keyCode == KeyCode.LeftControl) { isCtrlDown = false; if (controlType == ControlType.DraggingNewCommentBox) { controlType = ControlType.None; } } //开始拖拽新的注释框 if (isCtrlDown && controlType == ControlType.None && e.type == EventType.MouseDown && e.button == 0) { controlType = ControlType.DraggingNewCommentBox; startDraggingCommentBoxGraphPosition = WindowPositionToGraphPosition(windowMousePosition); endDraggingCommentBoxGraphPosition = startDraggingCommentBoxGraphPosition; e.Use(); } //更新新的注释框 if (controlType == ControlType.DraggingNewCommentBox && e.type == EventType.MouseDrag && e.button == 0) { endDraggingCommentBoxGraphPosition = WindowPositionToGraphPosition(windowMousePosition); e.Use(); } //结束新的注释框 if (isCtrlDown && controlType == ControlType.DraggingNewCommentBox && e.type == EventType.MouseUp && e.button == 0) { controlType = ControlType.None; CommentBoxView newCommentBox = new CommentBoxView(this, startDraggingCommentBoxGraphPosition, endDraggingCommentBoxGraphPosition); data.CurrentCommentBoxViewList.Add(newCommentBox); e.Use(); } //注释框操作 if (data.CurrentCommentBoxViewList.Count > 0 && !hasHoverdNodeInputLabel) { for (int i = 0; i < data.CurrentCommentBoxViewList.Count; i++) { CommentBoxView commentBoxView = data.CurrentCommentBoxViewList[i]; //右键点击注释框 if (controlType == ControlType.None && e.type == EventType.MouseDown && e.button == 1) { if (commentBoxView.Contains(zoomedMousePosition)) { OpenCommentBoxGenericMenu(commentBoxView, e.mousePosition); e.Use(); break; } } //拖拽编辑注释区域大小 if (controlType == ControlType.None && (e.type != EventType.Layout || e.type != EventType.Repaint)) { CommentBoxView.BoxEdge boxEdge = commentBoxView.AtEdge(zoomedMousePosition); if (boxEdge != CommentBoxView.BoxEdge.None) { MouseCursor cursorMode = (boxEdge == CommentBoxView.BoxEdge.Left || boxEdge == CommentBoxView.BoxEdge.Right) ? MouseCursor.ResizeHorizontal : MouseCursor.ResizeVertical; EditorGUIUtility.AddCursorRect(guiRect, cursorMode); //开始拖拽扩大 if (e.type == EventType.MouseDown && e.button == 0) { resizingCommentEdge = boxEdge; resizingCommentBox = commentBoxView; controlType = ControlType.ResizingCommentBox; e.Use(); } break; } } //双击编辑注释 if ((controlType == ControlType.None || controlType == ControlType.DraggingCommentBox) && e.type == EventType.MouseDown && e.button == 0) { if (commentBoxView.Contains(zoomedMousePosition)) { if (lastClickCommentBox == null || lastClickCommentBox != commentBoxView) { // Debug.Log("click once"); //一次点击可能是要拖拽了 controlType = ControlType.DraggingCommentBox; lastClickCommentBox = commentBoxView; draggingCommentBox = commentBoxView; lastClickCommentTime = EditorApplication.timeSinceStartup; e.Use(); break; } else if (lastClickCommentBox == commentBoxView) { double currentTime = EditorApplication.timeSinceStartup; if (currentTime - lastClickCommentTime <= 0.3f) { // Debug.Log("click twice"); controlType = ControlType.EditingComment; lastClickCommentBox.EnableEditComment(true); editingCommentBox = lastClickCommentBox; lastClickCommentBox = null; e.Use(); break; } else { // Debug.Log("click twice failed"); lastClickCommentBox = null; } } } } } } //右键点击面板 if (e.type == EventType.MouseDown && e.button == 1) { OpenGraphGenericMenu(e.mousePosition); e.Use(); } //改变注释框大小的时候,改变鼠标图标 if (controlType == ControlType.ResizingCommentBox) { MouseCursor cursorMode = (resizingCommentEdge == CommentBoxView.BoxEdge.Left || resizingCommentEdge == CommentBoxView.BoxEdge.Right) ? MouseCursor.ResizeHorizontal : MouseCursor.ResizeVertical; EditorGUIUtility.AddCursorRect(guiRect, cursorMode); } //编辑注释框大小 if (controlType == ControlType.ResizingCommentBox && e.type == EventType.MouseDrag && e.button == 0) { if (resizingCommentBox != null) { if (resizingCommentEdge != CommentBoxView.BoxEdge.None) { resizingCommentBox.Resizing(resizingCommentEdge, e.delta / data.GraphZoom); e.Use(); } } } //停止编辑注释框大小 if (controlType == ControlType.ResizingCommentBox && e.type == EventType.MouseUp && e.button == 0) { controlType = ControlType.None; resizingCommentBox = null; resizingCommentEdge = CommentBoxView.BoxEdge.None; e.Use(); } //拖拽注释框 if (controlType == ControlType.DraggingCommentBox && draggingCommentBox != null && e.type == EventType.MouseDrag && e.button == 0) { if (draggingCommentBox.Contains(zoomedMousePosition)) { draggingCommentBox.Drag(data.CurrentNodeList, e.delta / data.GraphZoom); e.Use(); } } //停止拖拽注释框 if (controlType == ControlType.DraggingCommentBox && draggingCommentBox != null && e.type == EventType.MouseUp && e.button == 0) { draggingCommentBox = null; controlType = ControlType.None; e.Use(); } //停止编辑注释框 if (e.type == EventType.MouseDown) { if (controlType == ControlType.EditingComment) { if (!editingCommentBox.Contains(zoomedMousePosition)) { controlType = ControlType.None; editingCommentBox.EnableEditComment(false); editingCommentBox = null; GUI.FocusControl(null); e.Use(); } } else { data.ClearSelectedNode(); GUI.FocusControl(null); } } //开始多选框 if (controlType == ControlType.None && e.type == EventType.MouseDrag && e.button == 0) { startMultiSelectionPos = e.mousePosition; controlType = ControlType.DraggingMultiSelection; e.Use(); } //更新多选框 if (controlType == ControlType.DraggingMultiSelection) { Rect multiSelectionRect = new Rect(); multiSelectionRect.position = NonZoomedWindowPositionToZoomedWindowPosition(startMultiSelectionPos); multiSelectionRect.max = NonZoomedWindowPositionToZoomedWindowPosition(e.mousePosition); data.UpdateSelectedNode(multiSelectionRect); } //结束多选框 if (controlType == ControlType.DraggingMultiSelection && e.type == EventType.MouseUp && e.button == 0) { controlType = ControlType.None; e.Use(); } //排除掉鼠标移出去之后,多选框还会继续拖拽的问题 if (!guiRect.Contains(e.mousePosition) && e.type != EventType.Layout && e.type != EventType.Repaint) { if (controlType == ControlType.DraggingMultiSelection) { controlType = ControlType.None; e.Use(); } } }
/// <summary> /// 只有一个port的情况下,这条线认为是正在拖拽连接线 /// </summary> /// <param name="draggingFromPort"></param> public ConnectionLineView(PortEditorView draggingFromPort) { this.draggingPort = draggingFromPort; }
public void DrawNodeGUI() { if (graph == null) { return; } PositionInWindow = graph.GraphPositionToWindowPosition(PositionInGraph); viewRect.center = PositionInWindow; if (isSelected) { Rect highLightRect = new Rect(viewRect); highLightRect.position = highLightRect.position - Vector2.one * 2f; highLightRect.max = highLightRect.max + Vector2.one * 4f; GUI.Box(highLightRect, "", Utility.GetGuiStyle("Highlight")); } //draw back ground if (ReflectionInfo.IsEntranceNode) { GUI.Box(viewRect, "", Utility.GetGuiStyle("EntranceNode")); } if (ReflectionInfo.Type.IsSubclassOf(typeof(GraphVariableNodeBase))) { GUI.Box(viewRect, "", Utility.GetGuiStyle("NodeCyan")); } else { GUI.Box(viewRect, "", Utility.GetGuiStyle("NodeBg")); } //draw node name GUI.Label(NodeNameRect, string.Format("({0}){1}", NodeId, ReflectionInfo.NodeName), Utility.GetGuiStyle("NodeName")); leftPortLayoutHelper.SetPosition(new Vector2(viewRect.x, viewRect.y + NodeNameRect.height + PortAreaPadding)); rightPortLayoutHelper.SetPosition(new Vector2(viewRect.x, viewRect.y + NodeNameRect.height + PortAreaPadding)); if (flowInPortView != null) { flowInPortView.portViewRect = leftPortLayoutHelper.GetRect(); } for (int i = 0; i < inputPortViewList.Count; i++) { InputPortEditorView inputPortView = inputPortViewList[i]; inputPortView.portViewRect = leftPortLayoutHelper.GetRect(); } if (flowOutPortViews.Length > 0) { for (int i = 0; i < flowOutPortViews.Length; i++) { FlowOutPortEditorView flowoutPortView = flowOutPortViews[i]; flowoutPortView.portViewRect = rightPortLayoutHelper.GetRect(); } } for (int i = 0; i < outputPortViewList.Count; i++) { OutputPortEditorView outputPortView = outputPortViewList[i]; outputPortView.portViewRect = rightPortLayoutHelper.GetRect(); } for (int i = 0; i < allPortList.Count; i++) { PortEditorView portView = allPortList[i]; portView.Draw(); } }