mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2026-02-12 14:32:35 +08:00
fixing file subflows ui, allowing export of widgets
This commit is contained in:
parent
1aa10090e6
commit
d53f65d1f3
@ -1,8 +1,4 @@
|
|||||||
import { app } from "../../scripts/app.js";
|
import { app } from "../../scripts/app.js";
|
||||||
import { api } from "../../scripts/api.js";
|
|
||||||
import { ComfyWidgets } from "/scripts/widgets.js";
|
|
||||||
const CONFIG = Symbol();
|
|
||||||
// const GET_CONFIG = Symbol();
|
|
||||||
import { GET_CONFIG } from "./widgetInputs.js";
|
import { GET_CONFIG } from "./widgetInputs.js";
|
||||||
|
|
||||||
function getConfig(widgetName) {
|
function getConfig(widgetName) {
|
||||||
@ -116,23 +112,6 @@ function getConfig(widgetName) {
|
|||||||
app.registerExtension({
|
app.registerExtension({
|
||||||
name: "Comfy.Subflow",
|
name: "Comfy.Subflow",
|
||||||
beforeRegisterNodeDef(nodeType, nodeData, app) {
|
beforeRegisterNodeDef(nodeType, nodeData, app) {
|
||||||
|
|
||||||
// console.log("in init")
|
|
||||||
// LiteGraph.registerNodeType(
|
|
||||||
// "InMemorySubflow",
|
|
||||||
// Object.assign(InMemorySubflow, {
|
|
||||||
// title: "InMemorySubflow",
|
|
||||||
// })
|
|
||||||
// );
|
|
||||||
|
|
||||||
// LiteGraph.registerNodeType(
|
|
||||||
// "FileSubflow",
|
|
||||||
// Object.assign(FileSubflow, {
|
|
||||||
// title: "FileSubflow",
|
|
||||||
// })
|
|
||||||
// );
|
|
||||||
|
|
||||||
// FileSubflow.category = "utils";
|
|
||||||
const refreshPins = (node, subflow) => {
|
const refreshPins = (node, subflow) => {
|
||||||
if(!subflow)
|
if(!subflow)
|
||||||
return;
|
return;
|
||||||
@ -157,28 +136,37 @@ app.registerExtension({
|
|||||||
const exports = subflowNode.properties?.exports;
|
const exports = subflowNode.properties?.exports;
|
||||||
if (exports) {
|
if (exports) {
|
||||||
let pinNum = 0;
|
let pinNum = 0;
|
||||||
for (const inputRef of exports.inputs) {
|
for (const exportedInput of exports.inputs) {
|
||||||
console.log(subflowNode.inputs);
|
const input = subflowNode.inputs.find(q => q.name === exportedInput.name);
|
||||||
const input = subflowNode.inputs.find(q => q.name === inputRef);
|
|
||||||
if (!input) continue;
|
if (!input) continue;
|
||||||
const { name, type, link, slot_index, ...extras } = input;
|
const { name, type, link, slot_index, ...extras } = input;
|
||||||
console.log("Input");
|
// console.log("Input");
|
||||||
console.log(input);
|
// console.log(input);
|
||||||
console.log(extras);
|
// console.log(extras);
|
||||||
if (extras.widget) {
|
// if (extras.widget) {
|
||||||
const w = extras.widget;
|
// // const w = extras.widget;
|
||||||
const config = getConfig.call(this, input.name) ?? [input.type, w.options || {}];
|
// // const config = getConfig.call(this, input.name) ?? [input.type, w.options || {}];
|
||||||
extras.widget[GET_CONFIG] = () => config;
|
// // console.log(config);
|
||||||
console.log(extras);
|
// // extras.widget[GET_CONFIG] = () => config;
|
||||||
console.log(input.type);
|
// // 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 );
|
node.addInput(input.name, input.type, extras );
|
||||||
inputSlots.push([subflowNode.id, pinNum]);
|
inputSlots.push([subflowNode.id, pinNum]);
|
||||||
pinNum++;
|
pinNum++;
|
||||||
}
|
}
|
||||||
pinNum = 0;
|
pinNum = 0;
|
||||||
for (const outputRef of exports.outputs) {
|
for (const exportedOutput of exports.outputs) {
|
||||||
const output = subflowNode.outputs.find(q => q.name === outputRef);
|
const output = subflowNode.outputs.find(q => q.name === exportedOutput.name);
|
||||||
if (!output) continue;
|
if (!output) continue;
|
||||||
node.addOutput(output.name, output.type);
|
node.addOutput(output.name, output.type);
|
||||||
outputSlots.push([subflowNode.id, pinNum]);
|
outputSlots.push([subflowNode.id, pinNum]);
|
||||||
@ -190,11 +178,65 @@ app.registerExtension({
|
|||||||
node.size[0] = 180;
|
node.size[0] = 180;
|
||||||
};
|
};
|
||||||
|
|
||||||
const refreshNode = async (node, subflow) => {
|
const refreshWidgets = (node, subflow, recoverValues) => {
|
||||||
|
if (!subflow)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (node.widgets) {
|
||||||
|
// Allow widgets to cleanup
|
||||||
|
let subflowWidget;
|
||||||
|
for (const w of node.widgets) {
|
||||||
|
if (w.type == "button") {
|
||||||
|
subflowWidget = w;
|
||||||
|
} else if (w.onRemove) {
|
||||||
|
w.onRemove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
node.widgets = [subflowWidget];
|
||||||
|
}
|
||||||
|
|
||||||
|
const subflowNodes = subflow.nodes;
|
||||||
|
let widgetIndex = 1;
|
||||||
|
for (const subflowNode of subflowNodes) {
|
||||||
|
const exports = subflowNode.properties?.exports;
|
||||||
|
if (exports) {
|
||||||
|
|
||||||
|
for (const exportedWidget of exports.widgets) {
|
||||||
|
let type = exportedWidget.config[0];
|
||||||
|
let options = type;
|
||||||
|
if (type instanceof Array) {
|
||||||
|
options = { values: type };
|
||||||
|
type = "combo";
|
||||||
|
} else {
|
||||||
|
options = exportedWidget.config[1];
|
||||||
|
}
|
||||||
|
if (type === "INT" || type === "FLOAT") {
|
||||||
|
type = "number";
|
||||||
|
}
|
||||||
|
const getWidgetCallback = (widgetIndex) => {
|
||||||
|
return (v) => {
|
||||||
|
console.log(node);
|
||||||
|
node.widgets_values[widgetIndex] = v;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let value = exportedWidget.value;
|
||||||
|
if (recoverValues) {
|
||||||
|
value = node.widgets_values[widgetIndex] ?? value;
|
||||||
|
}
|
||||||
|
node.addWidget(type, exportedWidget.name, value, getWidgetCallback(widgetIndex), options);
|
||||||
|
widgetIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const refreshNode = (node, subflow) => {
|
||||||
if (!subflow) return;
|
if (!subflow) return;
|
||||||
|
|
||||||
node.subflow = subflow;
|
node.subflow = subflow;
|
||||||
refreshPins(node, subflow);
|
refreshPins(node, subflow);
|
||||||
|
refreshWidgets(node, subflow, false);
|
||||||
|
|
||||||
node.size[0] = Math.max(100, LiteGraph.NODE_TEXT_SIZE * node.title.length * 0.45 + 160);
|
node.size[0] = Math.max(100, LiteGraph.NODE_TEXT_SIZE * node.title.length * 0.45 + 160);
|
||||||
};
|
};
|
||||||
@ -204,7 +246,8 @@ app.registerExtension({
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
if (nodeData.name == "FileSubflow") {
|
if (nodeData.name == "FileSubflow") {
|
||||||
nodeType.prototype.refreshNode = function(subflow) { refreshNode(this, subflow); };
|
nodeType.prototype.onConfigure = function() { refreshWidgets(this, this.subflow, true); };
|
||||||
|
nodeType.prototype.refreshNode = function(subflow) { refreshNode(this, subflow); };
|
||||||
nodeType.prototype.getExportedOutput = function(slot) { return this.subflow.extras.outputSlots[slot]; }
|
nodeType.prototype.getExportedOutput = function(slot) { return this.subflow.extras.outputSlots[slot]; }
|
||||||
nodeType.prototype.getExportedInput = function(slot) { return this.subflow.extras.inputSlots[slot]; }
|
nodeType.prototype.getExportedInput = function(slot) { return this.subflow.extras.inputSlots[slot]; }
|
||||||
|
|
||||||
|
|||||||
@ -12953,31 +12953,45 @@ LGraphNode.prototype.executeAction = function(action)
|
|||||||
};
|
};
|
||||||
|
|
||||||
LGraphCanvas.onMenuNodeExport = function(value, options, e, menu, node) {
|
LGraphCanvas.onMenuNodeExport = function(value, options, e, menu, node) {
|
||||||
|
console.log(node);
|
||||||
if (!node) {
|
if (!node) {
|
||||||
throw "no node passed";
|
throw "no node passed";
|
||||||
}
|
}
|
||||||
|
|
||||||
const getOption = ({ name, type, isExported }, pinType) => {
|
function getConfig(widgetName) {
|
||||||
const color = LGraphCanvas.link_type_colors[type];
|
const { nodeData } = this.constructor;
|
||||||
const innerHtml = `<span style='display: block; padding-left: 4px; color: ${color};'>${name}${isExported ? " (exported)" : ""} </span>`;
|
return nodeData?.input?.required[widgetName] ?? nodeData?.input?.optional?.[widgetName];
|
||||||
|
}
|
||||||
|
|
||||||
|
const getOption = (opt, pinType) => {
|
||||||
|
const color = LGraphCanvas.link_type_colors[opt.type];
|
||||||
|
const innerHtml = `<span style='display: block; padding-left: 4px; color: ${color};'>${opt.name}${opt.isExported ? " (exported)" : ""} </span>`;
|
||||||
return {
|
return {
|
||||||
name,
|
pinType,
|
||||||
type: pinType,
|
content: innerHtml,
|
||||||
content: innerHtml
|
...opt
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
let inputs = node.inputs ?? [];
|
let inputs = (node.inputs ?? []).filter((input) => !input.widget);
|
||||||
|
let widgets = (node.widgets ?? []).filter(({type}) => type != "button");
|
||||||
let outputs = node.outputs ?? [];
|
let outputs = node.outputs ?? [];
|
||||||
|
const isExported = (exports, v) => {
|
||||||
|
return exports.find(exp => exp.name == v.name) !== undefined;
|
||||||
|
};
|
||||||
if (node.properties?.exports?.inputs) {
|
if (node.properties?.exports?.inputs) {
|
||||||
inputs = inputs.map( input => ( {...input, isExported: node.properties.exports.inputs.includes(input.name) }) );
|
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) }) );
|
||||||
}
|
}
|
||||||
if (node.properties?.exports?.outputs) {
|
if (node.properties?.exports?.outputs) {
|
||||||
outputs = outputs.map( output => ( {...output, isExported: node.properties.exports.outputs.includes(output.name) }) );
|
outputs = outputs.map( output => ( {...output, isExported: isExported(node.properties.exports.outputs, output) }) );
|
||||||
}
|
}
|
||||||
|
|
||||||
const exportableVars = [
|
const exportableVars = [
|
||||||
...inputs.map((input) => getOption(input, "input")),
|
...inputs.map((input) => getOption(input, "input")),
|
||||||
|
...widgets.map((widget) => getOption(widget, "widget")),
|
||||||
null,
|
null,
|
||||||
...outputs.map((output) => getOption(output, "output")),
|
...outputs.map((output) => getOption(output, "output")),
|
||||||
];
|
];
|
||||||
@ -12995,23 +13009,42 @@ LGraphNode.prototype.executeAction = function(action)
|
|||||||
node.graph.beforeChange(/*?*/); //node
|
node.graph.beforeChange(/*?*/); //node
|
||||||
|
|
||||||
const exportVar = () => {
|
const exportVar = () => {
|
||||||
if (!node.properties.exports) {
|
if(!node.properties.exports) {
|
||||||
node.properties.exports = { inputs: [], outputs: [] };
|
node.properties.exports = {};
|
||||||
|
}
|
||||||
|
if (!node.properties.exports?.inputs) {
|
||||||
|
node.properties.exports.inputs = [];
|
||||||
|
}
|
||||||
|
if (!node.properties.exports?.widgets) {
|
||||||
|
node.properties.exports.widgets = [];
|
||||||
|
}
|
||||||
|
if (!node.properties.exports?.outputs) {
|
||||||
|
node.properties.exports.outputs = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const toggle = (arr, val) => {
|
const toggle = (arr, val) => {
|
||||||
if (arr.includes(val)) {
|
const i = arr.findIndex(ele => ele.name === val.name);
|
||||||
const i = arr.indexOf(val);
|
if ( i >= 0 ) {
|
||||||
arr.splice(i, 1);
|
arr.splice(i, 1);
|
||||||
} else {
|
} else {
|
||||||
arr.push(val);
|
const extras = {};
|
||||||
|
// copy widget params
|
||||||
|
console.log(val);
|
||||||
|
if (val.options) {
|
||||||
|
extras.config = getConfig.call(node, val.name) ?? [val.type, val.options || {}];
|
||||||
|
extras.value = val.value;
|
||||||
|
console.log(extras.config);
|
||||||
|
}
|
||||||
|
arr.push({ name: val.name, ...extras });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (v.type == "input") {
|
if (v.pinType == "input") {
|
||||||
toggle(node.properties.exports.inputs, v.name);
|
toggle(node.properties.exports.inputs, v);
|
||||||
} else if (v.type == "output") {
|
} else if(v.pinType == "widget") {
|
||||||
toggle(node.properties.exports.outputs, v.name);
|
toggle(node.properties.exports.widgets, v);
|
||||||
|
} else if (v.pinType == "output") {
|
||||||
|
toggle(node.properties.exports.outputs, v);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
exportVar();
|
exportVar();
|
||||||
|
|||||||
@ -570,7 +570,6 @@ export const ComfyWidgets = {
|
|||||||
document.body.append(fileInput);
|
document.body.append(fileInput);
|
||||||
|
|
||||||
// Create the button widget for selecting the files
|
// Create the button widget for selecting the files
|
||||||
console.log("adding widge")
|
|
||||||
uploadWidget = node.addWidget("button", "choose file with subflow", "subflow", () => {
|
uploadWidget = node.addWidget("button", "choose file with subflow", "subflow", () => {
|
||||||
fileInput.click();
|
fileInput.click();
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user