public OutputPortEditorView(NodeEditorView nodeView, OutputPortReflectionInfo outputPortReflectionInfo, int portId) : base(nodeView) { FlowType = FlowType.Out; this.outputPortReflectionInfo = outputPortReflectionInfo; this.portId = portId; }
private static NodeConfigInfo ConvertToNodeInfo(NodeEditorView nodeView) { NodeConfigInfo nodeConfigInfo = new NodeConfigInfo(); nodeConfigInfo.nodeId = nodeView.NodeId; nodeConfigInfo.positionInGraph = nodeView.PositionInGraph; nodeConfigInfo.nodeClassTypeName = nodeView.ReflectionInfo.Type.FullName; nodeConfigInfo.flowOutPortInfoList = new List <FlowOutPortConfigInfo>(); nodeConfigInfo.inputPortInfoList = new List <InputPortConfigInfo>(); //flow out info for (int i = 0; i < nodeView.flowOutPortViews.Length; i++) { FlowOutPortEditorView flowOutPort = nodeView.flowOutPortViews[i]; nodeConfigInfo.flowOutPortInfoList.Add(ConvertToFlowOutPortInfo(flowOutPort)); } //input info for (int i = 0; i < nodeView.inputPortViewList.Count; i++) { InputPortEditorView inputPort = nodeView.inputPortViewList[i]; nodeConfigInfo.inputPortInfoList.Add(ConvertToInputPortInfo(inputPort)); } return(nodeConfigInfo); }
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 InputPortEditorView(NodeEditorView nodeView, InputPortReflectionInfo inputPortReflectionInfo) : base(nodeView) { FlowType = FlowType.In; this.inputPortReflectionInfo = inputPortReflectionInfo; labelStyle = Utility.GetGuiStyle("InputLabel"); labelTextStyle = Utility.GetGuiStyle("InputLabelText"); }
/// <summary> /// 检查当前技能是否有入口节点 /// </summary> /// <returns></returns> public bool CheckHasEntranceNode() { for (int i = 0; i < nodeList.Count; i++) { NodeEditorView nodeView = nodeList[i]; if (nodeView.ReflectionInfo.Type.IsSubclassOf(typeof(EntranceNodeBase))) { return(true); } } return(false); }
void Reset() { if (data != null) { data.Clear(); } draggingNodeView = null; currentHoverPortView = null; currentHoverNodeView = null; controlType = ControlType.None; repaintTimer = EditorApplication.timeSinceStartup; }
/// <summary> /// 递归获取该节点创建sequence时需要包含的所有节点id /// 遇到CreateSequenceNode则停止往右探索 /// </summary> /// <returns></returns> public void GetSequenceNodesIdsRecursive(ref List <int> rightSideNodeIdList) { if (rightSideNodeIdList == null) { rightSideNodeIdList = new List <int>(); } if (flowOutPortViews != null) { for (int i = 0; i < flowOutPortViews.Length; i++) { List <PortEditorView> connectionPortList = flowOutPortViews[i].connectedPortList; for (int j = 0; j < connectionPortList.Count; j++) { NodeEditorView targetNode = connectionPortList[j].NodeView; int nodeId = targetNode.NodeId; if (!rightSideNodeIdList.Contains(nodeId)) { rightSideNodeIdList.Add(nodeId); if (!targetNode.ReflectionInfo.IsCreateSequenceNode) { targetNode.GetSequenceNodesIdsRecursive(ref rightSideNodeIdList); } } } } } for (int i = 0; i < outputPortViewList.Count; i++) { OutputPortEditorView outputPort = outputPortViewList[i]; List <PortEditorView> connectionPortList = outputPort.connectedPortList; for (int j = 0; j < connectionPortList.Count; j++) { NodeEditorView targetNode = connectionPortList[j].NodeView; int nodeId = targetNode.NodeId; if (!rightSideNodeIdList.Contains(nodeId)) { rightSideNodeIdList.Add(nodeId); if (!targetNode.ReflectionInfo.IsCreateSequenceNode) { targetNode.GetSequenceNodesIdsRecursive(ref rightSideNodeIdList); } } } } }
void DrawNodes() { if (data == null || data.CurrentNodeList == null) { return; } List <NodeEditorView> nodeViewList = data.CurrentNodeList; for (int i = 0; i < nodeViewList.Count; i++) { NodeEditorView nodeView = nodeViewList[i]; nodeView.DrawNodeGUI(); } }
public void UpdateSelectedNode(Rect selectionRect) { ClearSelectedNode(); for (int i = 0; i < CurrentNodeList.Count; i++) { NodeEditorView nodeView = CurrentNodeList[i]; if (nodeView.IsContainInRect(selectionRect)) { nodeView.isSelected = true; selectedNodeList.Add(nodeView); } } // Debug.Log("select node count: " + selectedNodeList.Count); }
void OpenNodeGenericMenu(NodeEditorView node, Vector2 mousePosition) { GenericMenu genericMenu = new GenericMenu(); genericMenu.AddItem(new GUIContent("删除该节点"), false, () => { if (node == null) { return; } data.DeleteNode(node); }); genericMenu.ShowAsContext(); }
/// <summary> /// 将节点放到队尾,这样在渲染的时候就可以让这个节点在最上面 /// </summary> public void PutNodeToListTail(int targetNodeIndex) { if (targetNodeIndex < 0 || targetNodeIndex >= CurrentNodeList.Count) { return; } if (targetNodeIndex == CurrentNodeList.Count - 1) { return; } NodeEditorView tailNode = CurrentNodeList[CurrentNodeList.Count - 1]; CurrentNodeList[CurrentNodeList.Count - 1] = CurrentNodeList[targetNodeIndex]; CurrentNodeList[targetNodeIndex] = tailNode; }
public void Drag(List <NodeEditorView> nodeViewList, Vector2 dragOffset) { rectInGraph.position += dragOffset; //同时,所有在注释框里面的节点要跟着被拖动 if (nodeViewList != null && nodeViewList.Count > 0) { for (int i = 0; i < nodeViewList.Count; i++) { NodeEditorView nodeEditorView = nodeViewList[i]; if (nodeEditorView.IsContainInRect(rectInWindow)) { nodeEditorView.Drag(dragOffset); } } } }
private static NodeEditorView ParseNodeInfo(NodeConfigInfo nodeConfigInfo, GraphEditorWindow graph) { string nodeTypeName = nodeConfigInfo.nodeClassTypeName; Type nodeType = Type.GetType(nodeTypeName + ",Assembly-CSharp"); if (nodeType == null) { Debug.LogErrorFormat("无法载入类型{0} ,该节点被跳过", nodeTypeName); return(null); } NodeReflectionInfo reflectionInfo = new NodeReflectionInfo(nodeType); NodeEditorView nodeView = new NodeEditorView(nodeConfigInfo.positionInGraph, graph, nodeConfigInfo.nodeId, reflectionInfo); return(nodeView); }
/// <summary> /// 每一种入口节点只允许存在一个 /// </summary> /// <param name="testType"></param> /// <returns></returns> public bool CheckDuplicateEntranceNode(Type testType) { if (!testType.IsSubclassOf(typeof(EntranceNodeBase))) { return(false); } for (int i = 0; i < nodeList.Count; i++) { NodeEditorView nodeView = nodeList[i]; if (nodeView.ReflectionInfo.Type == testType) { return(true); } } return(false); }
/// <summary> /// 图运行时节点信息 /// </summary> /// <returns></returns> private static byte[] ConvertToRuntimeInfo(List <NodeEditorView> nodeViewList, List <GraphVariableInfo> graphVariableInfoList, int graphId) { FlatBufferBuilder fbb = new FlatBufferBuilder(1024); Offset <NodeInfo>[] nodeInfoOffsets = new Offset <NodeInfo> [nodeViewList.Count]; List <int> commonNodeIdList = new List <int>(); List <int> entranceNodeIdList = new List <int>(); for (int i = 0; i < nodeViewList.Count; i++) { NodeEditorView nodeView = nodeViewList[i]; Offset <NodeInfo> nodeInfoOffset = ConvertToRuntimeNodeInfo(fbb, nodeView); nodeInfoOffsets[i] = nodeInfoOffset; if (nodeView.CheckNodeIsCommonNode()) { commonNodeIdList.Add(nodeView.NodeId); } if (nodeView.ReflectionInfo.IsEntranceNode) { entranceNodeIdList.Add(nodeView.NodeId); } } VectorOffset nodeVectorOffset = GraphInfo.CreateNodesVector(fbb, nodeInfoOffsets); //common node ids GraphInfo.StartCommonNodeIdsVector(fbb, commonNodeIdList.Count); for (int i = commonNodeIdList.Count - 1; i >= 0; i--) { fbb.AddInt(commonNodeIdList[i]); } VectorOffset commonNodeVectorOffset = fbb.EndVector(); //entrance node ids GraphInfo.StartEntranceNodeIdsVector(fbb, entranceNodeIdList.Count); for (int i = entranceNodeIdList.Count - 1; i >= 0; i--) { fbb.AddInt(entranceNodeIdList[i]); } VectorOffset entranceNodeVectorOffset = fbb.EndVector(); //graph variable infos int graphVariableCount = graphVariableInfoList.Count; Offset <FlatNode.Runtime.Flat.GraphVariableInfo>[] graphVariableInfoOffsets = new Offset <FlatNode.Runtime.Flat.GraphVariableInfo> [graphVariableCount]; for (int i = 0; i < graphVariableCount; i++) { graphVariableInfoOffsets[i] = ConvertToRuntimeGraphVariableInfo(fbb, graphVariableInfoList[i]); } VectorOffset graphVariableInfoVectorOffset = GraphInfo.CreateGraphVariableInfosVector(fbb, graphVariableInfoOffsets); GraphInfo.StartGraphInfo(fbb); GraphInfo.AddGraphId(fbb, graphId); GraphInfo.AddCommonNodeIds(fbb, commonNodeVectorOffset); GraphInfo.AddEntranceNodeIds(fbb, entranceNodeVectorOffset); GraphInfo.AddNodes(fbb, nodeVectorOffset); GraphInfo.AddGraphVariableInfos(fbb, graphVariableInfoVectorOffset); Offset <GraphInfo> offset = GraphInfo.EndGraphInfo(fbb); fbb.Finish(offset.Value); return(fbb.SizedByteArray()); }
/// <summary> /// 检查一个节点是否是通用节点。 /// 通用节点是指该节点不会从技能入口流入到或者取值不会从能够从技能入口流入到的节点取值。 /// 递归所有左Flow In节点和Input节点,如果能够访问到入口节点,则该节点不是通用节点。 /// </summary> /// <returns></returns> public bool CheckNodeIsCommonNode(HashSet <NodeEditorView> checkedNodeSet = null) { if (ReflectionInfo.Type.IsSubclassOf(typeof(EntranceNodeBase))) { return(false); } if (checkedNodeSet == null) { checkedNodeSet = new HashSet <NodeEditorView>(); } if (flowInPortView != null && flowInPortView.connectedPortList.Count > 0) { List <PortEditorView> connectionPortList = flowInPortView.connectedPortList; for (int i = 0; i < connectionPortList.Count; i++) { NodeEditorView nodeView = connectionPortList[i].NodeView; if (checkedNodeSet.Contains(nodeView)) { continue; } if (nodeView.ReflectionInfo.Type.IsSubclassOf(typeof(EntranceNodeBase))) { return(false); } checkedNodeSet.Add(nodeView); if (!nodeView.CheckNodeIsCommonNode(checkedNodeSet)) { return(false); } } } if (inputPortViewList.Count > 0) { for (int i = 0; i < inputPortViewList.Count; i++) { List <PortEditorView> connectionPortList = inputPortViewList[i].connectedPortList; for (int j = 0; j < connectionPortList.Count; j++) { NodeEditorView nodeView = connectionPortList[j].NodeView; if (checkedNodeSet.Contains(nodeView)) { continue; } if (nodeView.ReflectionInfo.Type.IsSubclassOf(typeof(EntranceNodeBase))) { return(false); } checkedNodeSet.Add(nodeView); if (!nodeView.CheckNodeIsCommonNode(checkedNodeSet)) { return(false); } } } } return(true); }
public FlowInPortEditorView(NodeEditorView nodeView) : base(nodeView) { this.FlowType = FlowType.In; flowInFromNodeId = -1; }
protected PortEditorView(NodeEditorView nodeView) { NodeView = nodeView; connectedPortList = new List <PortEditorView>(); }
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(); } } }
public static void SaveGraph(GraphEditorData data) { string jsonString = String.Empty; byte[] runtimeConfigBytes = null; bool isSuccess = true; try { //存储技能配置json文件,配置文件使用json是因为可读性好 GraphConfigInfo graphConfigInfo = new GraphConfigInfo { graphId = data.graphId, graphName = data.graphName, graphDescription = data.graphDescription, nodesList = new List <NodeConfigInfo>(), commentBoxInfoList = new List <CommentBoxInfo>(), graphVariableInfoList = new List <GraphVariableInfo>(), }; for (int i = 0; i < data.nodeList.Count; i++) { NodeEditorView nodeView = data.nodeList[i]; graphConfigInfo.nodesList.Add(ConvertToNodeInfo(nodeView)); } for (int i = 0; i < data.commentBoxViewList.Count; i++) { CommentBoxView commentBoxView = data.commentBoxViewList[i]; graphConfigInfo.commentBoxInfoList.Add(ConvertToCommentInfo(commentBoxView)); } for (int i = 0; i < data.graphVariableInfoList.Count; i++) { graphConfigInfo.graphVariableInfoList.Add(data.graphVariableInfoList[i].OnSerialized()); } jsonString = JsonUtility.ToJson(graphConfigInfo, true); runtimeConfigBytes = ConvertToRuntimeInfo(data.nodeList, data.graphVariableInfoList, data.graphId); } catch (Exception e) { isSuccess = false; Debug.LogError(e.Message); throw; } finally { if (isSuccess) { string graphEditorConfigFilePath = Path.Combine(Application.dataPath, string.Format("FlatNode/Editor/GraphSavedConfig/{0}.json", data.graphId)); File.WriteAllText(graphEditorConfigFilePath, jsonString); string graphRuntimeConfigFilePath = Path.Combine(Application.dataPath, string.Format("Resources/GraphRuntime/{0}.bytes", data.graphId)); string parentDirctoryPath = Directory.GetParent(graphRuntimeConfigFilePath).FullName; if (!Directory.Exists(parentDirctoryPath)) { Directory.CreateDirectory(parentDirctoryPath); } if (runtimeConfigBytes != null) { File.WriteAllBytes(graphRuntimeConfigFilePath, runtimeConfigBytes); } //更新所有图的记录文件 AddOrUpdateGraphsRecord(data); AssetDatabase.Refresh(); } } }
/// <summary> /// 根据input port的类型,将对应数据初始化 /// </summary> /// <param name="inputPortReflectionInfo"></param> /// <param name="type"></param> /// <param name="valueString"></param> /// <param name="nodeView"></param> private static void SetNodeInputVariableValue(InputPortReflectionInfo inputPortReflectionInfo, Type type, string valueString, NodeEditorView nodeView) { if (inputPortReflectionInfo.inputValueType != type) { Debug.LogErrorFormat("节点{0}中的Input Port {1} 的泛型改变了,之前是{2},现在是{3}", nodeView.ReflectionInfo.Type, inputPortReflectionInfo.PortName, type.FullName, inputPortReflectionInfo.inputValueType.FullName); return; } if (type == typeof(int)) { int value = int.Parse(valueString); inputPortReflectionInfo.SetInputNodeVariableValue(value); } else if (type == typeof(float)) { float value = float.Parse(valueString); inputPortReflectionInfo.SetInputNodeVariableValue(value); } else if (type == typeof(string)) { inputPortReflectionInfo.SetInputNodeVariableValue(valueString); } else if (type == typeof(bool)) { bool value = Boolean.Parse(valueString); inputPortReflectionInfo.SetInputNodeVariableValue(value); } else if (type.IsEnum) { object value = Enum.Parse(type, valueString); inputPortReflectionInfo.SetInputNodeVariableValue(value); } else if (type == typeof(List <int>)) { string[] splitString = valueString.Split('|'); List <int> value = new List <int>(); for (int i = 0; i < splitString.Length; i++) { value.Add(int.Parse(splitString[i])); } inputPortReflectionInfo.SetInputNodeVariableValue(value); } else if (type == typeof(LayerMaskWrapper)) { LayerMaskWrapper value = valueString; inputPortReflectionInfo.SetInputNodeVariableValue(value); } else if (type == typeof(VariableWrapper)) { int intValue; if (int.TryParse(valueString, out intValue)) { VariableWrapper variableWrapper = intValue; inputPortReflectionInfo.SetInputNodeVariableValue(variableWrapper); } else { Debug.LogErrorFormat("标记为VariableWrapper类型的input接口,但是它记录的值不是int类型的: {0}", valueString); } } }
private static void UpdateNodeViewData(NodeConfigInfo nodeConfigInfo, NodeEditorView nodeView, GraphEditorData data) { //flow in port--处理流出节点的时候顺便就处理了 //flow out port for (int i = 0; i < nodeConfigInfo.flowOutPortInfoList.Count; i++) { FlowOutPortConfigInfo flowOutPortConfigInfo = nodeConfigInfo.flowOutPortInfoList[i]; FlowOutPortEditorView flowOutPortView = GetFlowOutPortViewByPortName(nodeView.flowOutPortViews, flowOutPortConfigInfo.flowOutPortName); if (flowOutPortView == null) { Debug.LogFormat("节点{0}中找不到流出端口 <{1}> 了,该端口的连接被忽略", nodeView.ReflectionInfo.Type, flowOutPortConfigInfo.flowOutPortName); continue; } for (int j = 0; j < flowOutPortConfigInfo.targetNodeList.Count; j++) { int targetNodeId = flowOutPortConfigInfo.targetNodeList[j]; NodeEditorView targetNodeView = data.GetNode(targetNodeId); if (targetNodeView == null) { Debug.LogErrorFormat("无法找到节点{0},可能是配置损坏/更改了类名...", targetNodeId); continue; } if (targetNodeView.flowInPortView == null) { Debug.LogErrorFormat("节点类型{0}没有流入节点,是否节点性质发生了改变?", nodeView.ReflectionInfo.Type.FullName); continue; } ConnectionLineView connectionLineView = new ConnectionLineView(flowOutPortView, targetNodeView.flowInPortView, data); data.connectionLineList.Add(connectionLineView); } } //output port -- 不用配置 //input port for (int i = 0; i < nodeConfigInfo.inputPortInfoList.Count; i++) { InputPortConfigInfo inputPortConfigInfo = nodeConfigInfo.inputPortInfoList[i]; InputPortEditorView inputPortView = GetInputPortViewByPortName(nodeView.inputPortViewList, inputPortConfigInfo.portName); if (inputPortView == null) { Debug.LogFormat("节点{0}中无法找到接口名字为 <{1}> 的NodeInputVariable Field,该接口配置被跳过", nodeView.ReflectionInfo.Type.FullName, inputPortConfigInfo.portName); continue; } //没有连接到其他节点的情况 if (string.IsNullOrEmpty(inputPortConfigInfo.targetPortName)) { //设置默认值 Type valueType = Type.GetType(inputPortConfigInfo.nodeVariableGenericTypeName); if (valueType == null) { valueType = Type.GetType(inputPortConfigInfo.nodeVariableGenericTypeName + ",UnityEngine"); if (valueType == null) { valueType = Type.GetType(inputPortConfigInfo.nodeVariableGenericTypeName + ",Assembly-CSharp"); } } if (valueType == null) { Debug.LogErrorFormat("工程中找不到类型: {0}", inputPortConfigInfo.nodeVariableGenericTypeName); continue; } SetNodeInputVariableValue(inputPortView.inputPortReflectionInfo, valueType, inputPortConfigInfo.nodeVariableValue, nodeView); } //连接到其他节点的情况 else { NodeEditorView connectedToNodeView = data.GetNode(inputPortConfigInfo.targetNodeId); if (connectedToNodeView == null) { Debug.LogErrorFormat("节点 {0} 的input接口 {1} 找不到连接的节点{2}", nodeView.NodeId, inputPortConfigInfo.portName, inputPortConfigInfo.targetNodeId); continue; } OutputPortEditorView connectedToOutputPortView = GetOutputPortViewByPortName(connectedToNodeView.outputPortViewList, inputPortConfigInfo.targetPortName); if (connectedToOutputPortView == null) { Debug.LogFormat("找不到节点{0}中 接口名字为 <{1}> 的output接口,该接口的连接被跳过", connectedToNodeView.NodeId, inputPortConfigInfo.targetPortName); continue; } ConnectionLineView connectionLineView = new ConnectionLineView(inputPortView, connectedToOutputPortView, data); data.connectionLineList.Add(connectionLineView); } } }
public static GraphEditorData LoadGraph(GraphEditorWindow graph, int graphId) { GraphEditorData resultData = new GraphEditorData(); string graphEditorConfigFilePath = Path.Combine(Application.dataPath, string.Format("FlatNode/Editor/GraphSavedConfig/{0}.json", graphId)); if (!File.Exists(graphEditorConfigFilePath)) { Debug.LogErrorFormat("无法载入行为图配置文件: {0}", graphEditorConfigFilePath); } string jsonString = File.ReadAllText(graphEditorConfigFilePath); GraphConfigInfo graphConfigInfo = new GraphConfigInfo(); EditorJsonUtility.FromJsonOverwrite(jsonString, graphConfigInfo); //处理注释框 for (int i = 0; i < graphConfigInfo.commentBoxInfoList.Count; i++) { CommentBoxInfo commentBoxInfo = graphConfigInfo.commentBoxInfoList[i]; CommentBoxView commentBoxView = ParseCommentBoxInfo(commentBoxInfo, graph); resultData.commentBoxViewList.Add(commentBoxView); } //变量 for (int i = 0; i < graphConfigInfo.graphVariableInfoList.Count; i++) { if (!graphConfigInfo.graphVariableInfoList[i].Validate()) { continue; } resultData.graphVariableInfoList.Add(graphConfigInfo.graphVariableInfoList[i].OnDeserialized()); } //如果有节点无法解析出来(可能是改了类名称之类的),则需要跳过这些节点 HashSet <int> errorNodeIndexSet = new HashSet <int>(); //首先将所有的节点都生成 for (int i = 0; i < graphConfigInfo.nodesList.Count; i++) { NodeEditorView nodeView = ParseNodeInfo(graphConfigInfo.nodesList[i], graph); if (nodeView == null) { errorNodeIndexSet.Add(i); continue; } resultData.nodeList.Add(nodeView); } //然后再将所有节点的内容写进去,将节点连起来 int nodeIndex = 0; for (int i = 0; i < graphConfigInfo.nodesList.Count; i++) { if (errorNodeIndexSet.Contains(i)) { //skip continue; } UpdateNodeViewData(graphConfigInfo.nodesList[i], resultData.nodeList[nodeIndex], resultData); nodeIndex++; } resultData.graphId = graphConfigInfo.graphId; resultData.graphName = graphConfigInfo.graphName; resultData.graphDescription = graphConfigInfo.graphDescription; return(resultData); }
private static Offset <NodeInfo> ConvertToRuntimeNodeInfo(FlatBufferBuilder fbb, NodeEditorView nodeView) { FlowOutPortEditorView[] flowOutPortViews = nodeView.flowOutPortViews; Offset <NodeFlowOutPortInfo>[] flowOutInfoOffsets = new Offset <NodeFlowOutPortInfo> [flowOutPortViews.Length]; for (int i = 0; i < flowOutPortViews.Length; i++) { flowOutInfoOffsets[i] = ConvertToRuntimeFlowOutPortInfo(fbb, flowOutPortViews[i]); } List <InputPortEditorView> inputPortViewList = nodeView.inputPortViewList; Offset <NodeInputFieldInfo>[] inputPortInfoOffsets = new Offset <NodeInputFieldInfo> [inputPortViewList.Count]; for (int i = 0; i < inputPortViewList.Count; i++) { inputPortInfoOffsets[i] = ConvertToRuntimeInputPortInfo(fbb, inputPortViewList[i]); } //这里处理rightSideNodeIds数组 VectorOffset rightSideNodeIdsVectorOffset = new VectorOffset(); if (nodeView.ReflectionInfo.IsEntranceNode || nodeView.ReflectionInfo.IsCreateSequenceNode) { List <int> rightSideNodeIdList = new List <int>(); nodeView.GetSequenceNodesIdsRecursive(ref rightSideNodeIdList); if (rightSideNodeIdList.Count > 0) { rightSideNodeIdsVectorOffset = NodeInfo.CreateRightSideNodeIdsVector(fbb, rightSideNodeIdList.ToArray()); } } VectorOffset flowOutVectorOffset = NodeInfo.CreateFlowOutPortInfosVector(fbb, flowOutInfoOffsets); VectorOffset inputVectorOffset = NodeInfo.CreateInputPortInfosVector(fbb, inputPortInfoOffsets); StringOffset nodeTypeNameOffset = fbb.CreateString(nodeView.ReflectionInfo.Type.FullName); NodeInfo.StartNodeInfo(fbb); NodeInfo.AddNodeId(fbb, nodeView.NodeId); NodeInfo.AddNodeClassTypeName(fbb, nodeTypeNameOffset); NodeInfo.AddFlowOutPortInfos(fbb, flowOutVectorOffset); NodeInfo.AddInputPortInfos(fbb, inputVectorOffset); if (nodeView.ReflectionInfo.IsEntranceNode || nodeView.ReflectionInfo.IsCreateSequenceNode) { NodeInfo.AddRightSideNodeIds(fbb, rightSideNodeIdsVectorOffset); } return(NodeInfo.EndNodeInfo(fbb)); }
public FlowOutPortEditorView(NodeEditorView nodeView, NodeFlowOutPortDefineAttribute flowoutPortAttribute) : base(nodeView) { FlowType = FlowType.Out; this.flowoutPortAttribute = flowoutPortAttribute; }