@@ -69,7 +69,7 @@ import {
6969 TitleMode ,
7070} from "./types/globalEnums"
7171import { alignNodes , distributeNodes , getBoundaryNodes } from "./utils/arrange"
72- import { findFirstNode , getAllNestedItems } from "./utils/collections"
72+ import { findFirstNode , getAllNestedItems , isDraggingLink } from "./utils/collections"
7373import { toClass } from "./utils/type"
7474import { WIDGET_TYPE_MAP } from "./widgets/widgetMap"
7575
@@ -2253,6 +2253,7 @@ export class LGraphCanvas implements ConnectionColorContext {
22532253 output : null ,
22542254 pos,
22552255 direction : LinkDirection . RIGHT ,
2256+ link,
22562257 } )
22572258 }
22582259
@@ -2321,17 +2322,20 @@ export class LGraphCanvas implements ConnectionColorContext {
23212322 output : linked_node . outputs [ slot ] ,
23222323 pos : linked_node . getConnectionPos ( false , slot ) ,
23232324 afterRerouteId : link_info . parentId ,
2325+ link : link_info ,
23242326 }
2325- this . connecting_links = [ connecting ]
2327+ const connectingLinks = [ connecting ]
2328+ this . connecting_links = connectingLinks
23262329
23272330 pointer . onDragStart = ( ) => {
23282331 connecting . output = linked_node . outputs [ slot ]
23292332 }
23302333 pointer . onDragEnd = ( upEvent ) => {
2331- if ( this . allow_reconnect_links && ! LiteGraph . click_do_break_link_to ) {
2334+ const shouldDisconnect = this . #processConnectingLinks( upEvent , connectingLinks )
2335+
2336+ if ( shouldDisconnect && this . allow_reconnect_links && ! LiteGraph . click_do_break_link_to ) {
23322337 node . disconnectInput ( i )
23332338 }
2334- this . #processConnectingLinks( upEvent )
23352339 connecting . output = linked_node . outputs [ slot ]
23362340 this . connecting_links = null
23372341 }
@@ -2712,7 +2716,7 @@ export class LGraphCanvas implements ConnectionColorContext {
27122716 // Node background / title under the pointer
27132717 if ( ! linkOverWidget ) {
27142718 const targetSlotId = firstLink . node . findConnectByTypeSlot ( true , node , firstLink . output . type )
2715- if ( targetSlotId !== null && targetSlotId >= 0 ) {
2719+ if ( targetSlotId !== undefined && targetSlotId >= 0 ) {
27162720 node . getConnectionPos ( true , targetSlotId , pos )
27172721 highlightPos = pos
27182722 highlightInput = node . inputs [ targetSlotId ]
@@ -2739,7 +2743,7 @@ export class LGraphCanvas implements ConnectionColorContext {
27392743 if ( inputId === - 1 && outputId === - 1 ) {
27402744 const targetSlotId = firstLink . node . findConnectByTypeSlot ( false , node , firstLink . input . type )
27412745
2742- if ( targetSlotId !== null && targetSlotId >= 0 ) {
2746+ if ( targetSlotId !== undefined && targetSlotId >= 0 ) {
27432747 node . getConnectionPos ( false , targetSlotId , pos )
27442748 highlightPos = pos
27452749 }
@@ -2912,7 +2916,7 @@ export class LGraphCanvas implements ConnectionColorContext {
29122916
29132917 if ( this . connecting_links ?. length ) {
29142918 // node below mouse
2915- this . #processConnectingLinks( e )
2919+ this . #processConnectingLinks( e , this . connecting_links )
29162920 } else {
29172921 this . dirty_canvas = true
29182922
@@ -2944,25 +2948,33 @@ export class LGraphCanvas implements ConnectionColorContext {
29442948 return
29452949 }
29462950
2947- #processConnectingLinks( e : CanvasPointerEvent ) {
2948- const { graph, connecting_links } = this
2951+ #processConnectingLinks( e : CanvasPointerEvent , connecting_links : ConnectingLink [ ] ) : boolean | undefined {
2952+ const { graph } = this
29492953 if ( ! graph ) throw new NullGraphError ( )
2950- if ( ! connecting_links ) return
29512954
29522955 const { canvasX : x , canvasY : y } = e
29532956 const node = graph . getNodeOnPos ( x , y , this . visible_nodes )
29542957 const firstLink = connecting_links [ 0 ]
29552958
29562959 if ( node ) {
2960+ let madeNewLink : boolean | undefined
2961+
29572962 for ( const link of connecting_links ) {
29582963 // dragging a connection
29592964 this . #dirty( )
29602965
2966+ // One should avoid linking things to oneself
2967+ if ( node === link . node ) continue
2968+
29612969 // slot below mouse? connect
29622970 if ( link . output ) {
29632971 const slot = this . isOverNodeInput ( node , x , y )
29642972 if ( slot != - 1 ) {
2965- link . node . connect ( link . slot , node , slot , link . afterRerouteId )
2973+ // Trying to move link onto itself
2974+ if ( link . link ?. target_id === node . id && link . link ?. target_slot === slot ) return
2975+
2976+ const newLink = link . node . connect ( link . slot , node , slot , link . afterRerouteId )
2977+ madeNewLink ||= newLink !== null
29662978 } else if ( this . link_over_widget ) {
29672979 this . emitEvent ( {
29682980 subType : "connectingWidgetLink" ,
@@ -2974,28 +2986,33 @@ export class LGraphCanvas implements ConnectionColorContext {
29742986 } else {
29752987 // not on top of an input
29762988 // look for a good slot
2977- link . node . connectByType ( link . slot , node , link . output . type , {
2978- afterRerouteId : link . afterRerouteId ,
2979- } )
2989+ const slotIndex = link . node . findConnectByTypeSlot ( true , node , link . output . type )
2990+ if ( slotIndex !== undefined ) {
2991+ // Trying to move link onto itself
2992+ if ( link . link ?. target_id === node . id && link . link ?. target_slot === slotIndex ) return
2993+
2994+ const newLink = link . node . connect ( link . slot , node , slotIndex , link . afterRerouteId )
2995+ madeNewLink ||= newLink !== null
2996+ }
29802997 }
29812998 } else if ( link . input ) {
29822999 const slot = this . isOverNodeOutput ( node , x , y )
29833000
2984- if ( slot != - 1 ) {
3001+ const newLink = slot != - 1
29853002 // this is inverted has output-input nature like
2986- node . connect ( slot , link . node , link . slot , link . afterRerouteId )
2987- } else {
3003+ ? node . connect ( slot , link . node , link . slot , link . afterRerouteId )
29883004 // not on top of an input
29893005 // look for a good slot
2990- link . node . connectByTypeOutput (
3006+ : link . node . connectByTypeOutput (
29913007 link . slot ,
29923008 node ,
29933009 link . input . type ,
29943010 { afterRerouteId : link . afterRerouteId } ,
29953011 )
2996- }
3012+ madeNewLink ||= newLink !== null
29973013 }
29983014 }
3015+ return madeNewLink
29993016 } else if ( firstLink . input || firstLink . output ) {
30003017 // For external event only.
30013018 const linkReleaseContextExtended : LinkReleaseContextExtended = {
@@ -3033,6 +3050,7 @@ export class LGraphCanvas implements ConnectionColorContext {
30333050 }
30343051 }
30353052 }
3053+ return true
30363054 }
30373055 }
30383056
@@ -4897,6 +4915,8 @@ export class LGraphCanvas implements ConnectionColorContext {
48974915 const link = this . graph . _links . get ( link_id )
48984916 if ( ! link ) continue
48994917
4918+ const draggingLink = isDraggingLink ( link . id , this . connecting_links )
4919+
49004920 // find link info
49014921 const start_node = this . graph . getNodeById ( link . origin_id )
49024922 if ( start_node == null ) continue
@@ -4960,6 +4980,8 @@ export class LGraphCanvas implements ConnectionColorContext {
49604980 const startPos = prevReroute ?. pos ?? start_node_slotpos
49614981 reroute . calculateAngle ( this . last_draw_time , this . graph , startPos )
49624982
4983+ // Skip the first segment if it is being dragged
4984+ if ( j === 0 && draggingLink ?. input ) continue
49634985 this . renderLink (
49644986 ctx ,
49654987 startPos ,
@@ -4984,6 +5006,9 @@ export class LGraphCanvas implements ConnectionColorContext {
49845006 startControl = [ dist * reroute . cos , dist * reroute . sin ]
49855007 }
49865008
5009+ // Skip the last segment if it is being dragged
5010+ if ( draggingLink ?. output ) continue
5011+
49875012 // Use runtime fallback; TypeScript cannot evaluate this correctly.
49885013 const segmentStartPos = points . at ( - 2 ) ?? start_node_slotpos
49895014
@@ -5000,7 +5025,8 @@ export class LGraphCanvas implements ConnectionColorContext {
50005025 end_dir ,
50015026 { startControl } ,
50025027 )
5003- } else {
5028+ // Skip normal render when link is being dragged
5029+ } else if ( ! draggingLink ) {
50045030 this . renderLink (
50055031 ctx ,
50065032 start_node_slotpos ,
0 commit comments