diff --git a/nodes.py b/nodes.py index f5ec4e780..c592ac431 100644 --- a/nodes.py +++ b/nodes.py @@ -724,9 +724,8 @@ class SaveImage: def INPUT_TYPES(s): return {"required": {"images": ("IMAGE", ), - "filename_prefix": ("STRING", {"default": "ComfyUI"}), - "send to img": ("IMAGESEND", ) - }, + "filename_prefix": ("STRING", {"default": "ComfyUI"}) }, + "widget": {"send to img": ("IMAGESEND", )}, "hidden": {"prompt": "PROMPT", "extra_pnginfo": "EXTRA_PNGINFO"}, } @@ -807,10 +806,8 @@ class LoadImage: def INPUT_TYPES(s): if not os.path.exists(s.input_dir): os.makedirs(s.input_dir) - return {"required": - {"image": (sorted(os.listdir(s.input_dir)), ), - "recv img": (["disable", "enable"], ) - }, + return {"required": {"image": (sorted(os.listdir(s.input_dir)), ) }, + "widget": {"recv img": (["disable", "enable"], ) } } CATEGORY = "image" @@ -844,8 +841,8 @@ class LoadImageMask: def INPUT_TYPES(s): return {"required": {"image": (sorted(os.listdir(s.input_dir)), ), - "recv img": (["disable", "enable"], ), - "channel": (["alpha", "red", "green", "blue"], ),} + "channel": (["alpha", "red", "green", "blue"], ),}, + "widget": {"recv img": (["disable", "enable"], ) } } CATEGORY = "image" diff --git a/web/scripts/app.js b/web/scripts/app.js index 3f06629ee..43b1cfba8 100644 --- a/web/scripts/app.js +++ b/web/scripts/app.js @@ -576,6 +576,25 @@ class ComfyApp { } } + // widget type: visible. but prevent pass inputData to node function + const input_widgets = nodeData["input"]["widget"]; + for (const inputName in input_widgets) { + const inputData = input_widgets[inputName]; + const type = inputData[0]; + + if (Array.isArray(type)) { + // Enums e.g. latent rotation + let defaultValue = type[0]; + if (inputData[1] && inputData[1].default) { + defaultValue = inputData[1].default; + } + this.addWidget("combo", inputName, defaultValue, () => {}, { values: type }); + } + else { + Object.assign(config, widgets[type](this, inputName, inputData, app) || {}); + } + } + for (const output of nodeData["output"]) { this.addOutput(output, output); } diff --git a/web/scripts/widgets.js b/web/scripts/widgets.js index dca088d3d..56e9c533f 100644 --- a/web/scripts/widgets.js +++ b/web/scripts/widgets.js @@ -30,6 +30,50 @@ function seedWidget(node, inputName, inputData) { return { widget: seed, randomize }; } +function imagesendWidget(node, inputName, inputData, app) { + function showImage(node,uploadWidget,name) { + // Position the image somewhere sensible + if (!node.imageOffset) { + node.imageOffset = uploadWidget.last_y ? uploadWidget.last_y + 25 : 75; + } + + const img = new Image(); + img.onload = () => { + node.imgs = [img]; + app.graph.setDirtyCanvas(true); + }; + img.src = `/view?filename=${name}&type=input`; + } + + async function callback() { + if(node.images.length < 1) + return; + + const image_name = node.images[0].filename; + const copied = false; + + for(let i in app.graph._nodes) { + var n = app.graph._nodes[i]; + if(n.type == "LoadImage" || n.type == "LoadImageMask") { + const recvWidget = n.widgets.find((w) => w.name === "recv img"); + + if(recvWidget.value == "enable") { + // copy current node image to 'recv img' enabled node + + if(!copied) { + await api.sendOutputToInputImage(image_name); + } + + const thatImageWidget = n.widgets.find((w) => w.value === "image"); + await showImage(n,thatImageWidget,image_name); + } + } + } + } + + return { widget: node.addWidget("button", inputName, "", () => { callback(); }, {}) }; +} + function addMultilineWidget(node, name, defaultVal, app) { const widget = { type: "customtext", @@ -129,47 +173,7 @@ export const ComfyWidgets = { return { widget: node.addWidget("text", inputName, defaultVal, () => {}, {}) }; } }, - IMAGESEND(node, inputName) { - function showImage(node,uploadWidget,name) { - // Position the image somewhere sensible - if (!node.imageOffset) { - node.imageOffset = uploadWidget.last_y ? uploadWidget.last_y + 25 : 75; - } - - const img = new Image(); - img.onload = () => { - node.imgs = [img]; - app.graph.setDirtyCanvas(true); - }; - img.src = `/view?filename=${name}&type=input`; - } - - async function callback() { - const imageWidget = node.widgets.find((w) => w.name === "image"); - - const copied = false; - - for(let i in app.graph._nodes) { - var n = app.graph._nodes[i]; - if(n.type == "LoadImage" || n.type == "LoadImageMask") { - const recvWidget = n.widgets.find((w) => w.name === "recv img"); - - if(recvWidget.value == "enable") { - // copy current node image to 'recv img' enabled node - - if(!copied) { - api.sendOutputToInputImage(imageWidget.value); - } - - const thatImageWidget = n.widgets.find((w) => w.value === "image"); - await showImage(n,thatImageWidget,imageWidget.value); - } - } - } - } - - return { widget: node.addWidget("button", inputName, "", () => { callback(); }, {}) }; - }, + IMAGESEND:imagesendWidget, IMAGEUPLOAD(node, inputName, inputData, app) { const imageWidget = node.widgets.find((w) => w.name === "image"); let uploadWidget;