diff --git a/src/utils/migration/migrateReroute.ts b/src/utils/migration/migrateReroute.ts index 250b9eb00f..69252bcd10 100644 --- a/src/utils/migration/migrateReroute.ts +++ b/src/utils/migration/migrateReroute.ts @@ -67,6 +67,7 @@ export function createNewLinks( workflow: WorkflowJSON04, rerouteMap: Map ): { + reroutes: Reroute[] links: ComfyLink[] linkExtensions: LinkExtension[] } { @@ -112,17 +113,24 @@ export function createNewLinks( } // Populate linkIds on reroute nodes + // Remove all partially connected reroutes + const validLinkExtensions: LinkExtension[] = [] + const validReroutes: Set = new Set() + for (const linkExtension of linkExtensions) { let entry = rerouteMapByRerouteId.get(linkExtension.parentId) + const chainedReroutes: Reroute[] = [] while (entry) { const reroute = entry.reroute reroute.linkIds ??= [] reroute.linkIds.push(linkExtension.id) + chainedReroutes.push(reroute) if (reroute.parentId) { entry = rerouteMapByRerouteId.get(reroute.parentId) } else { + // Last reroute in the chain const rerouteNode = entry.rerouteNode const rerouteInputLink = linksMap.get( rerouteNode?.inputs?.[0]?.link ?? -1 @@ -142,13 +150,20 @@ export function createNewLinks( targetSlot, dataType ]) + + validLinkExtensions.push(linkExtension) + chainedReroutes.forEach((reroute) => validReroutes.add(reroute)) } entry = undefined } } } - return { links, linkExtensions } + return { + links, + linkExtensions: validLinkExtensions, + reroutes: Array.from(validReroutes) + } } /** @@ -177,16 +192,17 @@ export const migrateLegacyRerouteNodes = ( const rerouteMap = createReroutePoints(legacyRerouteNodes) // Create new links and link extensions - const { links, linkExtensions } = createNewLinks(workflow, rerouteMap) + const { links, linkExtensions, reroutes } = createNewLinks( + workflow, + rerouteMap + ) // Update the workflow newWorkflow.links = links newWorkflow.nodes = newWorkflow.nodes.filter( (node) => node.type !== 'Reroute' ) - newWorkflow.extra.reroutes = Array.from(rerouteMap.values()).map( - (entry) => entry.reroute - ) + newWorkflow.extra.reroutes = reroutes newWorkflow.extra.linkExtensions = linkExtensions return newWorkflow diff --git a/tests-ui/tests/utils/migration/migrateReroute.test.ts b/tests-ui/tests/utils/migration/migrateReroute.test.ts index 6facdbab9b..fb0c6bd688 100644 --- a/tests-ui/tests/utils/migration/migrateReroute.test.ts +++ b/tests-ui/tests/utils/migration/migrateReroute.test.ts @@ -14,7 +14,7 @@ describe('migrateReroute', () => { return JSON.parse(fileContent) as WorkflowJSON04 } - it.each(['branching.json', 'single_connected.json'])( + it.each(['branching.json', 'single_connected.json', 'floating.json'])( 'should correctly migrate %s', (fileName) => { // Load the legacy workflow diff --git a/tests-ui/tests/utils/migration/workflows/reroute/legacy/floating.json b/tests-ui/tests/utils/migration/workflows/reroute/legacy/floating.json new file mode 100644 index 0000000000..b31cd13e2a --- /dev/null +++ b/tests-ui/tests/utils/migration/workflows/reroute/legacy/floating.json @@ -0,0 +1,343 @@ +{ + "last_node_id": 31, + "last_link_id": 38, + "nodes": [ + { + "id": 4, + "type": "CheckpointLoaderSimple", + "pos": [ + 47.948699951171875, + 239.2628173828125 + ], + "size": [ + 315, + 98 + ], + "flags": {}, + "order": 0, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "MODEL", + "type": "MODEL", + "slot_index": 0, + "links": [] + }, + { + "name": "CLIP", + "type": "CLIP", + "slot_index": 1, + "links": [] + }, + { + "name": "VAE", + "type": "VAE", + "slot_index": 2, + "links": [ + 13, + 31 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.26", + "Node name for S&R": "CheckpointLoaderSimple" + }, + "widgets_values": [ + "v1-5-pruned-emaonly.safetensors" + ] + }, + { + "id": 13, + "type": "Reroute", + "pos": [ + 510, + 280 + ], + "size": [ + 75, + 26 + ], + "flags": {}, + "order": 1, + "mode": 0, + "inputs": [ + { + "name": "", + "type": "*", + "link": null + } + ], + "outputs": [ + { + "name": "", + "type": "*", + "slot_index": 0, + "links": [ + 21 + ] + } + ], + "properties": { + "showOutputText": false, + "horizontal": false + } + }, + { + "id": 12, + "type": "VAEDecode", + "pos": [ + 620, + 260 + ], + "size": [ + 210, + 46 + ], + "flags": {}, + "order": 5, + "mode": 0, + "inputs": [ + { + "name": "samples", + "type": "LATENT", + "link": null + }, + { + "name": "vae", + "type": "VAE", + "link": 21 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": null + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.26", + "Node name for S&R": "VAEDecode" + }, + "widgets_values": [] + }, + { + "id": 25, + "type": "Reroute", + "pos": [ + 401.49267578125, + 278.96600341796875 + ], + "size": [ + 75, + 26 + ], + "flags": {}, + "order": 4, + "mode": 0, + "inputs": [ + { + "name": "", + "type": "*", + "link": 31 + } + ], + "outputs": [ + { + "name": "", + "type": "VAE", + "links": [] + } + ], + "properties": { + "showOutputText": false, + "horizontal": false + } + }, + { + "id": 28, + "type": "Reroute", + "pos": [ + 401.874267578125, + 354.56207275390625 + ], + "size": [ + 75, + 26 + ], + "flags": {}, + "order": 2, + "mode": 0, + "inputs": [ + { + "name": "", + "type": "*", + "link": null + } + ], + "outputs": [ + { + "name": "", + "type": "*", + "links": null + } + ], + "properties": { + "showOutputText": false, + "horizontal": false + } + }, + { + "id": 30, + "type": "Reroute", + "pos": [ + 533.9331665039062, + 433.1788330078125 + ], + "size": [ + 75, + 26 + ], + "flags": {}, + "order": 6, + "mode": 0, + "inputs": [ + { + "name": "", + "type": "*", + "link": 37 + } + ], + "outputs": [ + { + "name": "", + "type": "*", + "links": null + } + ], + "properties": { + "showOutputText": false, + "horizontal": false + } + }, + { + "id": 29, + "type": "Reroute", + "pos": [ + 535.5305786132812, + 350.32513427734375 + ], + "size": [ + 75, + 26 + ], + "flags": {}, + "order": 7, + "mode": 0, + "inputs": [ + { + "name": "", + "type": "*", + "link": 38 + } + ], + "outputs": [ + { + "name": "", + "type": "*", + "links": [] + } + ], + "properties": { + "showOutputText": false, + "horizontal": false + } + }, + { + "id": 31, + "type": "Reroute", + "pos": [ + 405.2763671875, + 431.85943603515625 + ], + "size": [ + 75, + 26 + ], + "flags": {}, + "order": 3, + "mode": 0, + "inputs": [ + { + "name": "", + "type": "*", + "link": null + } + ], + "outputs": [ + { + "name": "", + "type": "*", + "links": [ + 37, + 38 + ] + } + ], + "properties": { + "showOutputText": false, + "horizontal": false + } + } + ], + "links": [ + [ + 21, + 13, + 0, + 12, + 1, + "VAE" + ], + [ + 31, + 4, + 2, + 25, + 0, + "*" + ], + [ + 37, + 31, + 0, + 30, + 0, + "*" + ], + [ + 38, + 31, + 0, + 29, + 0, + "*" + ] + ], + "groups": [], + "config": {}, + "extra": { + "ds": { + "scale": 1.2526143885641918, + "offset": [ + 449.14488520559655, + 200.06933385457722 + ] + } + }, + "version": 0.4 +} \ No newline at end of file diff --git a/tests-ui/tests/utils/migration/workflows/reroute/native/floating.json b/tests-ui/tests/utils/migration/workflows/reroute/native/floating.json new file mode 100644 index 0000000000..2d361b9ffa --- /dev/null +++ b/tests-ui/tests/utils/migration/workflows/reroute/native/floating.json @@ -0,0 +1,108 @@ +{ + "last_node_id": 31, + "last_link_id": 38, + "nodes": [ + { + "id": 4, + "type": "CheckpointLoaderSimple", + "pos": [ + 47.948699951171875, + 239.2628173828125 + ], + "size": [ + 315, + 98 + ], + "flags": {}, + "order": 0, + "mode": 0, + "inputs": [], + "outputs": [ + { + "name": "MODEL", + "type": "MODEL", + "slot_index": 0, + "links": [] + }, + { + "name": "CLIP", + "type": "CLIP", + "slot_index": 1, + "links": [] + }, + { + "name": "VAE", + "type": "VAE", + "slot_index": 2, + "links": [ + 13, + 31 + ] + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.26", + "Node name for S&R": "CheckpointLoaderSimple" + }, + "widgets_values": [ + "v1-5-pruned-emaonly.safetensors" + ] + }, + { + "id": 12, + "type": "VAEDecode", + "pos": [ + 620, + 260 + ], + "size": [ + 210, + 46 + ], + "flags": {}, + "order": 5, + "mode": 0, + "inputs": [ + { + "name": "samples", + "type": "LATENT", + "link": null + }, + { + "name": "vae", + "type": "VAE", + "link": 21 + } + ], + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": null + } + ], + "properties": { + "cnr_id": "comfy-core", + "ver": "0.3.26", + "Node name for S&R": "VAEDecode" + }, + "widgets_values": [] + } + ], + "links": [], + "groups": [], + "config": {}, + "extra": { + "ds": { + "scale": 1.2526143885641918, + "offset": [ + 449.14488520559655, + 200.06933385457722 + ] + }, + "reroutes": [], + "linkExtensions": [] + }, + "version": 0.4 +} \ No newline at end of file