From 90f54414ab7da195b8ab5a32e31ca042b105ee97 Mon Sep 17 00:00:00 2001 From: Christian Byrne Date: Mon, 11 Aug 2025 13:12:31 -0700 Subject: [PATCH] fix: Multiple links from reroute create single slot on SubgraphOutputNode (#4915) Co-authored-by: Claude --- src/lib/litegraph/src/canvas/LinkConnector.ts | 44 ++++++++++++++++++- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/src/lib/litegraph/src/canvas/LinkConnector.ts b/src/lib/litegraph/src/canvas/LinkConnector.ts index 8dea4c7a0e..ea57a3a6f9 100644 --- a/src/lib/litegraph/src/canvas/LinkConnector.ts +++ b/src/lib/litegraph/src/canvas/LinkConnector.ts @@ -17,6 +17,8 @@ import type { INodeInputSlot, INodeOutputSlot } from '@/lib/litegraph/src/interfaces' +import { EmptySubgraphInput } from '@/lib/litegraph/src/subgraph/EmptySubgraphInput' +import { EmptySubgraphOutput } from '@/lib/litegraph/src/subgraph/EmptySubgraphOutput' import { Subgraph } from '@/lib/litegraph/src/subgraph/Subgraph' import type { SubgraphInput } from '@/lib/litegraph/src/subgraph/SubgraphInput' import { SubgraphInputNode } from '@/lib/litegraph/src/subgraph/SubgraphInputNode' @@ -640,8 +642,27 @@ export class LinkConnector { const output = ioNode.getSlotInPosition(canvasX, canvasY) if (!output) throw new Error('No output slot found for link.') + // Track the actual slot to use for all connections + let targetSlot = output + for (const link of renderLinks) { - link.connectToSubgraphOutput(output, this.events) + link.connectToSubgraphOutput(targetSlot, this.events) + + // If we just connected to an EmptySubgraphOutput, check if we should reuse the slot + if (output instanceof EmptySubgraphOutput && ioNode.slots.length > 0) { + // Get the last created slot (newest one) + const createdSlot = ioNode.slots[ioNode.slots.length - 1] + + // Only reuse the slot if the next link's type would be compatible + // Otherwise, keep using EmptySubgraphOutput to create a new slot + const nextLink = renderLinks[renderLinks.indexOf(link) + 1] + if (nextLink && link.fromSlot.type === nextLink.fromSlot.type) { + targetSlot = createdSlot + } else { + // Reset to EmptySubgraphOutput for different types + targetSlot = output + } + } } } else if ( connectingTo === 'output' && @@ -650,8 +671,27 @@ export class LinkConnector { const input = ioNode.getSlotInPosition(canvasX, canvasY) if (!input) throw new Error('No input slot found for link.') + // Same logic for SubgraphInputNode if needed + let targetSlot = input + for (const link of renderLinks) { - link.connectToSubgraphInput(input, this.events) + link.connectToSubgraphInput(targetSlot, this.events) + + // If we just connected to an EmptySubgraphInput, check if we should reuse the slot + if (input instanceof EmptySubgraphInput && ioNode.slots.length > 0) { + // Get the last created slot (newest one) + const createdSlot = ioNode.slots[ioNode.slots.length - 1] + + // Only reuse the slot if the next link's type would be compatible + // Otherwise, keep using EmptySubgraphInput to create a new slot + const nextLink = renderLinks[renderLinks.indexOf(link) + 1] + if (nextLink && link.fromSlot.type === nextLink.fromSlot.type) { + targetSlot = createdSlot + } else { + // Reset to EmptySubgraphInput for different types + targetSlot = input + } + } } } else { console.error(