From 2a3054a91f219c0f318f8a8fe89352288542e322 Mon Sep 17 00:00:00 2001 From: Sammy Franklin Date: Tue, 24 Oct 2023 22:11:11 -0700 Subject: [PATCH] cleaing up; making subflows compatible with backend --- web/extensions/core/subflow.js | 138 +-------------------------------- web/lib/litegraph.core.js | 16 ++-- web/scripts/app.js | 19 +++-- 3 files changed, 27 insertions(+), 146 deletions(-) diff --git a/web/extensions/core/subflow.js b/web/extensions/core/subflow.js index 66a3aca8d..81e0c8105 100644 --- a/web/extensions/core/subflow.js +++ b/web/extensions/core/subflow.js @@ -1,113 +1,4 @@ import { app } from "../../scripts/app.js"; -import { GET_CONFIG } from "./widgetInputs.js"; - -function getConfig(widgetName) { - const { nodeData } = this.constructor; - return nodeData?.input?.required[widgetName] ?? nodeData?.input?.optional?.[widgetName]; -} - -// class InMemorySubflow extends LGraphNode { -// constructor(title) { -// super(title ?? "InMemorySubflow"); -// } - -// onConfigure() { -// console.log(this); -// } - -// getExportedOutput(slot) { -// return this.subflow.extras.outputSlots[slot]; -// }; - -// getExportedInput(slot) { -// return this.subflow.extras.inputSlots[slot]; -// }; - -// async refreshNode(subflow) { -// if (!subflow) return; -// this.updateSubflowPrompt(subflow); -// this.refreshPins(subflow); -// } - -// refreshPins(subflow) { -// if(!subflow) -// return; - -// subflow.extras = { inputSlots: [], outputSlots: [] }; -// const { inputSlots } = subflow.extras; -// const { outputSlots } = subflow.extras; - -// // remove all existing pins -// const numInputs = this.inputs?.length ?? 0; -// const numOutputs = this.outputs?.length ?? 0; -// for(let i = numInputs-1; i > -1; i--) { -// this.removeInput(i); -// } -// for(let i = numOutputs-1; i > -1; i--) { -// this.removeOutput(i); -// } - -// const subflowNodes = subflow.nodes; -// // add the new pins and keep track of where the exported vars go to within the inner nodes -// for (const subflowNode of subflowNodes) { -// const exports = subflowNode.properties?.exports; -// if (exports) { -// let pinNum = 0; -// for (const inputRef of exports.inputs) { -// console.log(subflowNode.inputs); -// const input = subflowNode.inputs.find(q => q.name === inputRef); -// if (!input) continue; -// const { name, type, link, slot_index, ...extras } = input; -// console.log("Input"); -// console.log(input); -// console.log(extras); -// if (extras.widget) { -// extras.widget[GET_CONFIG] = () => config; -// } -// this.addInput(input.name, input.type, extras ); -// inputSlots.push([subflowNode.id, pinNum]); -// pinNum++; -// } -// pinNum = 0; -// for (const outputRef of exports.outputs) { -// const output = subflowNode.outputs.find(q => q.name === outputRef); -// if (!output) continue; -// this.addOutput(output.name, output.type); -// outputSlots.push([subflowNode.id, pinNum]); -// pinNum++; -// } -// } -// } - -// this.size[0] = 180; -// }; - -// updateSubflowPrompt(subflow) { -// this.subflow = subflow; -// }; -// } - -// class FileSubflow extends InMemorySubflow { -// constructor() { -// super("FileSubflow"); - -// console.log("constructor called"); -// // ComfyWidgets.SUBFLOWUPLOAD(this, null, null, app); -// } - -// async refreshNode(subflow) { -// if (!subflow) return; - -// this.updateSubflowPrompt(subflow); -// this.refreshPins(subflow); - -// this.size[0] = this.computeSizeX(); -// } - -// computeSizeX() { -// return Math.max(100, LiteGraph.NODE_TEXT_SIZE * this.title.length * 0.45 + 160); -// } -// } app.registerExtension({ name: "Comfy.Subflow", @@ -140,25 +31,6 @@ app.registerExtension({ const input = subflowNode.inputs.find(q => q.name === exportedInput.name); if (!input) continue; const { name, type, link, slot_index, ...extras } = input; - // console.log("Input"); - // console.log(input); - // console.log(extras); - // if (extras.widget) { - // // const w = extras.widget; - // // const config = getConfig.call(this, input.name) ?? [input.type, w.options || {}]; - // // console.log(config); - // // extras.widget[GET_CONFIG] = () => config; - // // console.log(extras); - // // console.log(input.type); - // // console.log(subflowNode); - // // const convertedWidget = subflowNode.widgets.find((w) => w.name == inputRef); - // // node.widgets.push(convertedWidget); - // // const widgetIndex = subflowNode.inputs.findIndex(q => q.name === inputRef); - // // const widget = node.addWidget("number", inputRef, 1, ()=>{}, {min: 0, max:1, step:.1, round:.01, precision:2}); - // // node.widgets.push({type: "number", name: inputRef, value: 1, callback: ()=>{}, options: {min: 0, max:1, step:.1, round:.01, precision:2}}); - // console.log("adding widget", exportedInput.name); - // // convertToInput(node, widget, config); - // } node.addInput(input.name, input.type, extras ); inputSlots.push([subflowNode.id, pinNum]); @@ -215,8 +87,10 @@ app.registerExtension({ } const getWidgetCallback = (widgetIndex) => { return (v) => { - console.log(node); - node.widgets_values[widgetIndex] = v; + if (v !== null && node.widgets_values) { + node.widgets_values[widgetIndex] = v; + } + return subflowNode.id; } }; let value = exportedWidget.value; @@ -241,10 +115,6 @@ app.registerExtension({ node.size[0] = Math.max(100, LiteGraph.NODE_TEXT_SIZE * node.title.length * 0.45 + 160); }; - // if (nodeData.name == "InMemorySubflow") { - // Object.assign(nodeData, new InMemorySubflow()); - // } - if (nodeData.name == "FileSubflow") { nodeType.prototype.onConfigure = function() { refreshWidgets(this, this.subflow, true); }; nodeType.prototype.refreshNode = function(subflow) { refreshNode(this, subflow); }; diff --git a/web/lib/litegraph.core.js b/web/lib/litegraph.core.js index 959a26c1f..e05f5fca5 100644 --- a/web/lib/litegraph.core.js +++ b/web/lib/litegraph.core.js @@ -12969,7 +12969,10 @@ LGraphNode.prototype.executeAction = function(action) return { pinType, content: innerHtml, - ...opt + type: opt.type, + value: opt.value, + name: opt.name, + options: opt.options }; }; @@ -12980,13 +12983,13 @@ LGraphNode.prototype.executeAction = function(action) return exports.find(exp => exp.name == v.name) !== undefined; }; if (node.properties?.exports?.inputs) { - inputs = inputs.map( input => ( {...input, isExported: isExported(node.properties.exports.inputs, input) }) ); + inputs = inputs.map( input => ( {...input, isExported: isExported(node.properties.exports.inputs, input)} )); } if (node.properties?.exports?.widgets) { - widgets = widgets.map( widget => ( {...widget, isExported: isExported(node.properties.exports.widgets, widget) }) ); + widgets = widgets.map( widget => ( {...widget, isExported: isExported(node.properties.exports.widgets, widget)} )); } if (node.properties?.exports?.outputs) { - outputs = outputs.map( output => ( {...output, isExported: isExported(node.properties.exports.outputs, output) }) ); + outputs = outputs.map( output => ( {...output, isExported: isExported(node.properties.exports.outputs, output)} )); } const exportableVars = [ @@ -13029,11 +13032,9 @@ LGraphNode.prototype.executeAction = function(action) } else { const extras = {}; // copy widget params - console.log(val); if (val.options) { - extras.config = getConfig.call(node, val.name) ?? [val.type, val.options || {}]; + extras.config = [val.type, val.options || {}]; extras.value = val.value; - console.log(extras.config); } arr.push({ name: val.name, ...extras }); } @@ -14072,6 +14073,7 @@ LGraphNode.prototype.executeAction = function(action) !options.ignore_item_callbacks && value.disabled !== true ) { + console.log("value", value); //item callback var r = value.callback.call( this, diff --git a/web/scripts/app.js b/web/scripts/app.js index c1311060f..12c492829 100644 --- a/web/scripts/app.js +++ b/web/scripts/app.js @@ -1590,7 +1590,7 @@ export class ComfyApp { */ async graphToPrompt(graph=this.graph) { let subflowNodeIdOffset = graph.last_node_id; - const subflowIdMapping = {}; + const subflowIdOffsets = {}; const workflow = graph.serialize(); const output = {}; @@ -1628,7 +1628,7 @@ export class ComfyApp { for_subflow: String(node.id) // keep reference of parent node }; } - subflowIdMapping[node.id] = subflowNodeIdOffset; + subflowIdOffsets[node.id] = subflowNodeIdOffset; subflowNodeIdOffset += Object.keys(node.subflow).length; } @@ -1641,7 +1641,16 @@ export class ComfyApp { for (const i in widgets) { const widget = widgets[i]; if (!widget.options || widget.options.serialize !== false) { - inputs[widget.name] = widget.serializeValue ? await widget.serializeValue(n, i) : widget.value; + if (node.subflow) { + if (widget.type !== "button") { + // use the callback to obtain node reference + const forNode = widget.callback(null); + const widgetNode = subflowIdOffsets[node.id] + forNode; + output[ widgetNode ].inputs[widget.name] = widget.serializeValue ? await widget.serializeValue(n, i) : widget.value; + } + } else { + inputs[widget.name] = widget.serializeValue ? await widget.serializeValue(n, i) : widget.value; + } } } } @@ -1650,7 +1659,7 @@ export class ComfyApp { if (inputNode.subflow) { // input should be mapped to inner node const [ localOriginId, originSlot ] = inputNode.getExportedOutput(inputSlot); - const originId = subflowIdMapping[inputNode.id] + localOriginId; + const originId = subflowIdOffsets[inputNode.id] + localOriginId; return [String(originId), parseInt(originSlot)]; } @@ -1699,7 +1708,7 @@ export class ComfyApp { if (node.subflow) { // inner node's input should be used const [ localTargetId, targetSlot ] = node.getExportedInput(link.target_slot); - const targetId = subflowIdMapping[node.id] + localTargetId; + const targetId = subflowIdOffsets[node.id] + localTargetId; output[ String(targetId) ].inputs[ node.inputs[targetSlot].name ] = getInputRef(parent, link.origin_slot); }