/// <summary> /// Returns the node at the specified canvas-space position in the specified editor and returns a possible focused knob aswell /// </summary> public static Node NodeAtPosition(NodeEditorState editorState, Vector2 canvasPos, out NodeKnob focusedKnob) { focusedKnob = null; if (NodeEditorInputSystem.shouldIgnoreInput(editorState)) { return(null); } NodeCanvas canvas = editorState.canvas; for (int nodeCnt = canvas.nodes.Count - 1; nodeCnt >= 0; nodeCnt--) { // Check from top to bottom because of the render order Node node = canvas.nodes [nodeCnt]; if (node.rect.Contains(canvasPos)) { return(node); } for (int knobCnt = 0; knobCnt < node.nodeKnobs.Count; knobCnt++) { // Check if any nodeKnob is focused instead if (node.nodeKnobs[knobCnt].GetCanvasSpaceKnob().Contains(canvasPos)) { focusedKnob = node.nodeKnobs[knobCnt]; return(node); } } } return(null); }
/// <summary> /// Setup of the base framework. Enough to manage and calculate canvases. /// </summary> private static void setupBaseFramework() { CheckEditorPath(); // Init Resource system. Can be called anywhere else, too, if it's needed before. ResourceManager.SetDefaultResourcePath(editorPath + "Resources/"); // Run fetching algorithms searching the script assemblies for Custom Nodes / Connection Types / NodeCanvas Types ConnectionTypes.FetchTypes(); NodeTypes.FetchNodes(); NodeCanvasManager.GetAllCanvasTypes(); // Setup Callback system NodeEditorCallbacks.SetupReceivers(); NodeEditorCallbacks.IssueOnEditorStartUp(); // Init input NodeEditorInputSystem.SetupInput(); #if UNITY_EDITOR UnityEditor.EditorApplication.update -= Update; UnityEditor.EditorApplication.update += Update; #endif initiatedBase = true; }
public static Node NodeAtPosition(NodeEditorState editorState, Vector2 canvasPos, out NodeKnob focusedKnob) { focusedKnob = null; if (NodeEditorInputSystem.shouldIgnoreInput(editorState)) { return(null); } NodeCanvas canvas = editorState.canvas; for (int num = canvas.nodes.Count - 1; num >= 0; num--) { Node node = canvas.nodes[num]; if (node.rect.Contains(canvasPos)) { return(node); } for (int i = 0; i < node.nodeKnobs.Count; i++) { if (node.nodeKnobs[i].GetCanvasSpaceKnob().Contains(canvasPos)) { focusedKnob = node.nodeKnobs[i]; return(node); } } } return(null); }
/// <summary> /// Re-Inits the NodeCanvas regardless of whetehr it was initiated before /// </summary> public static void ReInit(bool GUIFunction) { CheckEditorPath(); // Init Resource system. Can be called anywhere else, too, if it's needed before. ResourceManager.SetDefaultResourcePath(editorPath + "Resources/"); // Init NE GUI. I may throw an error if a texture was not found. if (!NodeEditorGUI.Init(GUIFunction)) { InitiationError = true; return; } // Run fetching algorithms searching the script assemblies for Custom Nodes / Connection Types ConnectionTypes.FetchTypes(); NodeTypes.FetchNodes(); // Setup Callback system NodeEditorCallbacks.SetupReceivers(); NodeEditorCallbacks.IssueOnEditorStartUp(); // Init GUIScaleUtility. This fetches reflected calls and my throw a message notifying about incompability. GUIScaleUtility.CheckInit(); // Init input NodeEditorInputSystem.SetupInput(); #if UNITY_EDITOR UnityEditor.EditorApplication.update -= Update; UnityEditor.EditorApplication.update += Update; RepaintClients(); #endif initiated = GUIFunction; }
/// <summary> /// Gets a NodeGroup under the mouse. If multiple groups are adressed, the group lowest in the pin hierarchy is returned. /// </summary> private static NodeGroup GroupAtPosition(NodeEditorState state, Vector2 canvasPos) { if (NodeEditorInputSystem.shouldIgnoreInput(state)) { return(null); } for (int i = state.canvas.groups.Count - 1; i >= 0; i--) { NodeGroup group = state.canvas.groups[i]; if (group.headerRect.Contains(canvasPos) || group.rect.Contains(canvasPos)) { return(group); } } return(null); }
/// <summary> /// Gets a NodeGroup under the mouse. If multiple groups are adressed, the smallest is returned. /// </summary> private static NodeGroup GroupAtPosition(NodeEditorState state, Vector2 canvasPos) { if (NodeEditorInputSystem.shouldIgnoreInput(state)) { return(null); } NodeCanvas canvas = state.canvas; for (int groupCnt = canvas.groups.Count - 1; groupCnt >= 0; groupCnt--) { if (canvas.groups [groupCnt].rect.Contains(canvasPos) || canvas.groups [groupCnt].headerRect.Contains(canvasPos)) { return(canvas.groups [groupCnt]); } } return(null); }
/// <summary> /// Gets a NodeGroup under the mouse that requires input (header or border). If multiple groups are adressed, the group lowest in the pin hierarchy is returned. /// 获取鼠标点击的需要执行操作的Group(Header或Border),如果找到了多个group,则只处理第一个group /// </summary> private static NodeGroup GroupAtPositionInput(NodeEditorState state, Vector2 canvasPos) { if (NodeEditorInputSystem.shouldIgnoreInput(state)) { return(null); } for (int i = state.canvas.groups.Count - 1; i >= 0; i--) { NodeGroup group = state.canvas.groups[i]; BorderSelection border; if (group.headerRect.Contains(canvasPos) || CheckBorderSelection(state, group.bodyRect, canvasPos, out border)) { return(group); } } return(null); }
/// <summary> /// Returns the node at the specified canvas-space position in the specified editor and returns a possible focused knob aswell /// </summary> public static Node NodeAtPosition(NodeEditorState editorState, Vector2 canvasPos, out ConnectionKnob focusedKnob) { focusedKnob = null; if (editorState == null || NodeEditorInputSystem.shouldIgnoreInput(editorState)) { return(null); } NodeCanvas canvas = editorState.canvas; for (int nodeCnt = canvas.nodes.Count - 1; nodeCnt >= 0; nodeCnt--) { // Check from top to bottom because of the render order Node node = canvas.nodes [nodeCnt]; if (node.ClickTest(canvasPos, out focusedKnob)) { return(node); // Node is clicked on } } return(null); }
public static void InitSystem() { _inst = AssetDatabase.LoadAssetAtPath <NodeSystemSetting>(ASSET_PATH); bool hasExist = _inst != null; if (!hasExist) { _inst = CreateInstance <NodeSystemSetting>(); AssetDatabase.CreateAsset(_inst, ASSET_PATH); } ConnectionPortStyles.InitSystem(out _inst.portStyles, out _inst.valueTypes); NodeTypes.InitSystem(out _inst.nodeDatas); NodeCanvasManager.InitSystem(out _inst.canvasDatas); ConnectionPortManager.InitSystem(out _inst.nodePortDec); ConnectionPortManager.InitSystem(out _inst.nodePortDec); ImportExportManager.InitSystem(out _inst.ioFormats); NodeEditorInputSystem.InitSystem(out _inst.eventHandlers, out _inst.hotkeyHandlers, out _inst.contextEntries, out _inst.contextFillers); }
public static void ReInit(bool GUIFunction) { CheckEditorPath(); ResourceManager.SetDefaultResourcePath(editorPath + "Resources/"); if (!NodeEditorGUI.Init(GUIFunction)) { InitiationError = true; } else { ConnectionTypes.FetchTypes(); NodeTypes.FetchNodes(); NodeCanvasManager.GetAllCanvasTypes(); NodeEditorCallbacks.SetupReceivers(); NodeEditorCallbacks.IssueOnEditorStartUp(); GUIScaleUtility.CheckInit(); NodeEditorInputSystem.SetupInput(); initiated = GUIFunction; } }
/// <summary> /// Draws the Node Canvas on the screen in the rect specified by editorState without one-time wrappers like GUISkin and OverlayGUI. Made for nested Canvases (WIP) /// </summary> private static void DrawSubCanvas(NodeCanvas nodeCanvas, NodeEditorState editorState) { if (!editorState.drawing) { return; } BeginEditingCanvas(nodeCanvas, editorState); if (Event.current.type == EventType.Repaint) { // Draw Background when Repainting // Offset from origin in tile units Vector2 tileOffset = new Vector2(-(curEditorState.zoomPos.x * curEditorState.zoom + curEditorState.panOffset.x) / NodeEditorGUI.Background.width, ((curEditorState.zoomPos.y - curEditorState.canvasRect.height) * curEditorState.zoom + curEditorState.panOffset.y) / NodeEditorGUI.Background.height); // Amount of tiles Vector2 tileAmount = new Vector2(Mathf.Round(curEditorState.canvasRect.width * curEditorState.zoom) / NodeEditorGUI.Background.width, Mathf.Round(curEditorState.canvasRect.height * curEditorState.zoom) / NodeEditorGUI.Background.height); // Draw tiled background GUI.DrawTextureWithTexCoords(curEditorState.canvasRect, NodeEditorGUI.Background, new Rect(tileOffset, tileAmount)); } // Handle input events NodeEditorInputSystem.HandleInputEvents(curEditorState); if (Event.current.type != EventType.Layout) { curEditorState.ignoreInput = new List <Rect> (); } // We're using a custom scale method, as default one is messing up clipping rect Rect canvasRect = curEditorState.canvasRect; curEditorState.zoomPanAdjust = GUIScaleUtility.BeginScale(ref canvasRect, curEditorState.zoomPos, curEditorState.zoom, NodeEditorGUI.isEditorWindow, false); // ---- BEGIN SCALE ---- // Some features which require zoomed drawing: if (curEditorState.navigate) { // Draw a curve to the origin/active node for orientation purposes Vector2 startPos = (curEditorState.selectedNode != null? curEditorState.selectedNode.rect.center : curEditorState.panOffset) + curEditorState.zoomPanAdjust; Vector2 endPos = Event.current.mousePosition; RTEditorGUI.DrawLine(startPos, endPos, Color.green, null, 3); RepaintClients(); } if (curEditorState.connectOutput != null) { // Draw the currently drawn connection NodeOutput output = curEditorState.connectOutput; Vector2 startPos = output.GetGUIKnob().center; Vector2 startDir = output.GetDirection(); Vector2 endPos = Event.current.mousePosition; Vector2 endDir = -startDir; // NodeEditorGUI.GetSecondConnectionVector (startPos, endPos, startDir); <- causes unpleasant jumping when switching polarity NodeEditorGUI.OptimiseBezierDirections(startPos, ref startDir, endPos, ref endDir); NodeEditorGUI.DrawConnection(startPos, startDir, endPos, endDir, output.typeData.Color); RepaintClients(); } // Draw the groups below everything else for (int groupCnt = 0; groupCnt < curNodeCanvas.groups.Count; groupCnt++) { curNodeCanvas.groups [groupCnt].DrawGroup(); } // Push the active node to the top of the draw order. if (Event.current.type == EventType.Layout && curEditorState.selectedNode != null) { curNodeCanvas.nodes.Remove(curEditorState.selectedNode); curNodeCanvas.nodes.Add(curEditorState.selectedNode); } // Draw the transitions and connections. Has to be drawn before nodes as transitions originate from node centers for (int nodeCnt = 0; nodeCnt < curNodeCanvas.nodes.Count; nodeCnt++) { curNodeCanvas.nodes [nodeCnt].DrawConnections(); } // Draw the nodes for (int nodeCnt = 0; nodeCnt < curNodeCanvas.nodes.Count; nodeCnt++) { Node node = curNodeCanvas.nodes [nodeCnt]; node.DrawNode(); if (Event.current.type == EventType.Repaint) { node.DrawKnobs(); } } // ---- END SCALE ---- // End scaling group GUIScaleUtility.EndScale(); // Handle input events with less priority than node GUI controls NodeEditorInputSystem.HandleLateInputEvents(curEditorState); EndEditingCanvas(); }
/// <summary> /// Draws the Node Canvas on the screen in the rect specified by editorState without one-time wrappers like GUISkin and OverlayGUI. Made for nested Canvases (WIP) /// </summary> private static void DrawSubCanvas(NodeCanvas nodeCanvas, NodeEditorState editorState) { if (!editorState.drawing) { return; } // Store and restore later on in case of this being a nested Canvas NodeCanvas prevNodeCanvas = curNodeCanvas; NodeEditorState prevEditorState = curEditorState; curNodeCanvas = nodeCanvas; curEditorState = editorState; if (Event.current.type == EventType.Repaint) { // Draw Background when Repainting // Size in pixels the inividual background tiles will have on screen float width = curEditorState.zoom / NodeEditorGUI.Background.width; float height = curEditorState.zoom / NodeEditorGUI.Background.height; // Offset of the grid relative to the GUI origin Vector2 offset = curEditorState.zoomPos + curEditorState.panOffset / curEditorState.zoom; // Rect in UV space that defines how to tile the background texture Rect uvDrawRect = new Rect(-offset.x * width, (offset.y - curEditorState.canvasRect.height) * height, curEditorState.canvasRect.width * width, curEditorState.canvasRect.height * height); GUI.DrawTextureWithTexCoords(curEditorState.canvasRect, NodeEditorGUI.Background, uvDrawRect); } // Handle input events NodeEditorInputSystem.HandleInputEvents(curEditorState); if (Event.current.type != EventType.Layout) { curEditorState.ignoreInput = new List <Rect> (); } // We're using a custom scale method, as default one is messing up clipping rect Rect canvasRect = curEditorState.canvasRect; curEditorState.zoomPanAdjust = GUIScaleUtility.BeginScale(ref canvasRect, curEditorState.zoomPos, curEditorState.zoom, false); // ---- BEGIN SCALE ---- // Some features which require zoomed drawing: if (curEditorState.navigate) { // Draw a curve to the origin/active node for orientation purposes Vector2 startPos = (curEditorState.selectedNode != null? curEditorState.selectedNode.rect.center : curEditorState.panOffset) + curEditorState.zoomPanAdjust; Vector2 endPos = Event.current.mousePosition; RTEditorGUI.DrawLine(startPos, endPos, Color.green, null, 3); RepaintClients(); } if (curEditorState.connectOutput != null) { // Draw the currently drawn connection NodeOutput output = curEditorState.connectOutput; Vector2 startPos = output.GetGUIKnob().center; Vector2 startDir = output.GetDirection(); Vector2 endPos = Event.current.mousePosition; // There is no specific direction of the end knob so we pick the best according to the relative position Vector2 endDir = NodeEditorGUI.GetSecondConnectionVector(startPos, endPos, startDir); NodeEditorGUI.DrawConnection(startPos, startDir, endPos, endDir, output.typeData.Color); RepaintClients(); } // Push the active node to the top of the draw order. if (Event.current.type == EventType.Layout && curEditorState.selectedNode != null) { curNodeCanvas.nodes.Remove(curEditorState.selectedNode); curNodeCanvas.nodes.Add(curEditorState.selectedNode); } // Draw the transitions and connections. Has to be drawn before nodes as transitions originate from node centers for (int nodeCnt = 0; nodeCnt < curNodeCanvas.nodes.Count; nodeCnt++) { curNodeCanvas.nodes [nodeCnt].DrawConnections(); } // Draw the nodes for (int nodeCnt = 0; nodeCnt < curNodeCanvas.nodes.Count; nodeCnt++) { Node node = curNodeCanvas.nodes [nodeCnt]; node.DrawNode(); if (Event.current.type == EventType.Repaint) { node.DrawKnobs(); } } // ---- END SCALE ---- // End scaling group GUIScaleUtility.EndScale(); // Handle input events with less priority than node GUI controls NodeEditorInputSystem.HandleLateInputEvents(curEditorState); curNodeCanvas = prevNodeCanvas; curEditorState = prevEditorState; }
/// <summary> /// Draws the Node Canvas on the screen in the rect specified by editorState without one-time wrappers like GUISkin and OverlayGUI. Made for nested Canvases (WIP) /// </summary> private static void DrawSubCanvas(NodeCanvas nodeCanvas, NodeEditorState editorState) { if (!editorState.drawing) { return; } BeginEditingCanvas(nodeCanvas, editorState); if (curNodeCanvas == null || curEditorState == null || !curEditorState.drawing) { return; } if (Event.current.type == EventType.Repaint) { // Draw Background when Repainting // Offset from origin in tile units Vector2 tileOffset = new Vector2( -(curEditorState.zoomPos.x * curEditorState.zoom + curEditorState.panOffset.x) / NodeEditorGUI.Background.width, ((curEditorState.zoomPos.y - curEditorState.canvasRect.height) * curEditorState.zoom + curEditorState.panOffset.y) / NodeEditorGUI.Background.height); // Amount of tiles Vector2 tileAmount = new Vector2(Mathf.Round(curEditorState.canvasRect.width * curEditorState.zoom) / NodeEditorGUI.Background.width, Mathf.Round(curEditorState.canvasRect.height * curEditorState.zoom) / NodeEditorGUI.Background.height); // Draw tiled background GUI.DrawTextureWithTexCoords(curEditorState.canvasRect, NodeEditorGUI.Background, new Rect(tileOffset, tileAmount)); } // Handle input events NodeEditorInputSystem.HandleInputEvents(curEditorState); HandleMultipleSelect(); if (Event.current.type != EventType.Layout) { curEditorState.ignoreInput = new List <Rect>(); } // We're using a custom scale method, as default one is messing up clipping rect Rect canvasRect = curEditorState.canvasRect; curEditorState.zoomPanAdjust = GUIScaleUtility.BeginScale(ref canvasRect, curEditorState.zoomPos, curEditorState.zoom, NodeEditorGUI.isEditorWindow, false); // ---- BEGIN SCALE ---- // Some features which require zoomed drawing: if (curEditorState.navigate) { // Draw a curve to the origin/active node for orientation purposes Vector2 startPos = (curEditorState.selectedNodes.Count > 0? curEditorState.selectedNodes[0].rect.center : curEditorState.panOffset) + curEditorState.zoomPanAdjust; Vector2 endPos = Event.current.mousePosition; RTEditorGUI.DrawLine(startPos, endPos, Color.green, null, 3); RepaintClients(); } if (curEditorState.connectKnob != null) { // Draw the currently drawn connection curEditorState.connectKnob.DrawConnection(Event.current.mousePosition); RepaintClients(); } // Draw the groups below everything else for (int groupCnt = 0; groupCnt < curNodeCanvas.groups.Count; groupCnt++) { NodeGroup group = curNodeCanvas.groups[groupCnt]; if (Event.current.type == EventType.Layout) { group.isClipped = !curEditorState.canvasViewport.Overlaps(group.fullAABBRect); } if (!group.isClipped) { group.DrawGroup(); } } // Push the active node to the top of the draw order. if (Event.current.type == EventType.Layout && curEditorState.selectedNodes.Count > 0) { foreach (var node in curEditorState.selectedNodes) { curNodeCanvas.nodes.Remove(node); curNodeCanvas.nodes.Add(node); } } // Draw the transitions and connections. Has to be drawn before nodes as transitions originate from node centers for (int nodeCnt = 0; nodeCnt < curNodeCanvas.nodes.Count; nodeCnt++) { curNodeCanvas.nodes[nodeCnt].DrawConnections(); } // Draw the nodes for (int nodeCnt = 0; nodeCnt < curNodeCanvas.nodes.Count; nodeCnt++) { Node node = curNodeCanvas.nodes[nodeCnt]; if (Event.current.type == EventType.Layout) { node.isClipped = !curEditorState.canvasViewport.Overlaps(curNodeCanvas.nodes[nodeCnt].fullAABBRect); } if (!node.isClipped || node.ForceGUIDawOffScreen) { node.DrawNode(); if (Event.current.type == EventType.Repaint) { node.DrawKnobs(); } } } // ---- END SCALE ---- // End scaling group GUIScaleUtility.EndScale(); // Handle input events with less priority than node GUI controls NodeEditorInputSystem.HandleLateInputEvents(curEditorState); EndEditingCanvas(); }
/// <summary> /// Draws the Node Canvas on the screen in the rect specified by editorState without one-time wrappers like GUISkin and OverlayGUI. Made for nested Canvases (WIP) /// </summary> private static void DrawSubCanvas(NodeCanvas nodeCanvas, NodeEditorState editorState) { if (!editorState.drawing) { return; } BeginEditingCanvas(nodeCanvas, editorState); if (curNodeCanvas == null || curEditorState == null || !curEditorState.drawing) { return; } if (Event.current.type == EventType.Repaint) { //绘制NodeEditor背景 EditorGUI.DrawRect(curEditorState.canvasRect, new Color(28 / 255f, 28 / 255f, 28 / 255f)); } // Handle input events NodeEditorInputSystem.HandleInputEvents(curEditorState); HandleMultipleSelect(); if (Event.current.type != EventType.Layout) { curEditorState.ignoreInput = new List <Rect>(); } // We're using a custom scale method, as default one is messing up clipping rect Rect canvasRect = curEditorState.canvasRect; curEditorState.zoomPanAdjust = GUIScaleUtility.BeginScale(ref canvasRect, curEditorState.zoomPos, curEditorState.zoom, NodeEditorGUI.isEditorWindow, false); // 开始绘制缩放区域 if (curEditorState.connectKnob != null) { // Draw the currently drawn connection curEditorState.connectKnob.DrawConnection(Event.current.mousePosition); RepaintClients(); } // Draw the groups below everything else for (int groupCnt = 0; groupCnt < curNodeCanvas.groups.Count; groupCnt++) { NodeGroup group = curNodeCanvas.groups[groupCnt]; if (Event.current.type == EventType.Layout) { group.isClipped = !curEditorState.canvasViewport.Overlaps(group.fullAABBRect); } if (!group.isClipped) { group.DrawGroup(); } } // Draw the transitions and connections. Has to be drawn before nodes as transitions originate from node centers for (int nodeCnt = 0; nodeCnt < curNodeCanvas.nodes.Count; nodeCnt++) { curNodeCanvas.nodes[nodeCnt].DrawConnections(); } // Draw the nodes for (int nodeCnt = 0; nodeCnt < curNodeCanvas.nodes.Count; nodeCnt++) { Node node = curNodeCanvas.nodes[nodeCnt]; if (Event.current.type == EventType.Layout) { node.isClipped = !curEditorState.canvasViewport.Overlaps(curNodeCanvas.nodes[nodeCnt].fullAABBRect); } if (node.isClipped) { continue; } node.DrawNode(); if (Event.current.type == EventType.Repaint) { node.DrawKnobs(); } } // ---- END SCALE ---- // End scaling group GUIScaleUtility.EndScale(); // Handle input events with less priority than node GUI controls NodeEditorInputSystem.HandleLateInputEvents(curEditorState); EndEditingCanvas(); }
private static void DrawSubCanvas(NodeCanvas nodeCanvas, NodeEditorState editorState) { if (editorState.drawing) { NodeCanvas nodeCanvas2 = curNodeCanvas; NodeEditorState nodeEditorState = curEditorState; curNodeCanvas = nodeCanvas; curEditorState = editorState; if (Event.current.type == EventType.Repaint) { float num = curEditorState.zoom / (float)NodeEditorGUI.Background.width; float num2 = curEditorState.zoom / (float)NodeEditorGUI.Background.height; Vector2 vector = curEditorState.zoomPos + curEditorState.panOffset / curEditorState.zoom; GUI.DrawTextureWithTexCoords(texCoords: new Rect((0f - vector.x) * num, (vector.y - curEditorState.canvasRect.height) * num2, curEditorState.canvasRect.width * num, curEditorState.canvasRect.height * num2), position: curEditorState.canvasRect, image: NodeEditorGUI.Background); } NodeEditorInputSystem.HandleInputEvents(curEditorState); if (Event.current.type != EventType.Layout) { curEditorState.ignoreInput = new List <Rect>(); } Rect rect = curEditorState.canvasRect; curEditorState.zoomPanAdjust = GUIScaleUtility.BeginScale(ref rect, curEditorState.zoomPos, curEditorState.zoom, false); if (curEditorState.navigate) { Vector2 startPos = ((!((UnityEngine.Object)curEditorState.selectedNode != (UnityEngine.Object)null)) ? curEditorState.panOffset : curEditorState.selectedNode.rect.center) + curEditorState.zoomPanAdjust; Vector2 mousePosition = Event.current.mousePosition; RTEditorGUI.DrawLine(startPos, mousePosition, Color.green, null, 3f); RepaintClients(); } if ((UnityEngine.Object)curEditorState.connectOutput != (UnityEngine.Object)null) { NodeOutput connectOutput = curEditorState.connectOutput; Vector2 center = connectOutput.GetGUIKnob().center; Vector2 direction = connectOutput.GetDirection(); Vector2 mousePosition2 = Event.current.mousePosition; Vector2 secondConnectionVector = NodeEditorGUI.GetSecondConnectionVector(center, mousePosition2, direction); NodeEditorGUI.DrawConnection(center, direction, mousePosition2, secondConnectionVector, connectOutput.typeData.Color); RepaintClients(); } if (Event.current.type == EventType.Layout && (UnityEngine.Object)curEditorState.selectedNode != (UnityEngine.Object)null) { curNodeCanvas.nodes.Remove(curEditorState.selectedNode); curNodeCanvas.nodes.Add(curEditorState.selectedNode); } for (int i = 0; i < curNodeCanvas.nodes.Count; i++) { curNodeCanvas.nodes[i].DrawConnections(); } for (int j = 0; j < curNodeCanvas.nodes.Count; j++) { Node node = curNodeCanvas.nodes[j]; node.DrawNode(); if (Event.current.type == EventType.Repaint) { node.DrawKnobs(); } } GUIScaleUtility.EndScale(); NodeEditorInputSystem.HandleLateInputEvents(curEditorState); curNodeCanvas = nodeCanvas2; curEditorState = nodeEditorState; } }