/// <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);
        }
Example #4
0
        /// <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;
        }
Example #5
0
 /// <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);
        }
Example #7
0
        /// <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);
        }
Example #8
0
        /// <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);
        }
Example #9
0
        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();
        }
Example #12
0
        /// <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;
        }
Example #13
0
        /// <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();
        }
Example #14
0
        /// <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;
     }
 }