From 606e2b4fd83fc44e1f0b403e1f076501db8c3749 Mon Sep 17 00:00:00 2001 From: Luis Quesada Date: Fri, 21 Aug 2026 19:02:32 +0200 Subject: [PATCH] Fixed javascript for Nodes 2.0, which was not storing settings --- js/showcontrol.js | 106 +++++++++++++++++++++++++++++----------------- pyproject.toml | 2 +- 2 files changed, 67 insertions(+), 41 deletions(-) diff --git a/js/showcontrol.js b/js/showcontrol.js index b7cbf69..8e32e80 100644 --- a/js/showcontrol.js +++ b/js/showcontrol.js @@ -9,28 +9,20 @@ function inpaintCropAndStitchHandler(node) { toggleWidget(node, findWidgetByName(node, "preresize_min_height")); toggleWidget(node, findWidgetByName(node, "preresize_max_width")); toggleWidget(node, findWidgetByName(node, "preresize_max_height")); - if (findWidgetByName(node, "preresize").value == true) { + const preresize = findWidgetByName(node, "preresize"); + if (preresize && preresize.value == true) { toggleWidget(node, findWidgetByName(node, "preresize_mode"), true); - if (findWidgetByName(node, "preresize_mode").value == "ensure minimum resolution") { - toggleWidget(node, findWidgetByName(node, "preresize_min_width"), true); - toggleWidget(node, findWidgetByName(node, "preresize_min_height"), true); - } - else if (findWidgetByName(node, "preresize_mode").value == "ensure minimum and maximum resolution") { - toggleWidget(node, findWidgetByName(node, "preresize_min_width"), true); - toggleWidget(node, findWidgetByName(node, "preresize_min_height"), true); - toggleWidget(node, findWidgetByName(node, "preresize_max_width"), true); - toggleWidget(node, findWidgetByName(node, "preresize_max_height"), true); - } - else if (findWidgetByName(node, "preresize_mode").value == "ensure maximum resolution") { - toggleWidget(node, findWidgetByName(node, "preresize_max_width"), true); - toggleWidget(node, findWidgetByName(node, "preresize_max_height"), true); - } + toggleWidget(node, findWidgetByName(node, "preresize_min_width"), true); + toggleWidget(node, findWidgetByName(node, "preresize_min_height"), true); + toggleWidget(node, findWidgetByName(node, "preresize_max_width"), true); + toggleWidget(node, findWidgetByName(node, "preresize_max_height"), true); } toggleWidget(node, findWidgetByName(node, "extend_up_factor")); toggleWidget(node, findWidgetByName(node, "extend_down_factor")); toggleWidget(node, findWidgetByName(node, "extend_left_factor")); toggleWidget(node, findWidgetByName(node, "extend_right_factor")); - if (findWidgetByName(node, "extend_for_outpainting").value == true) { + const extendForOutpainting = findWidgetByName(node, "extend_for_outpainting"); + if (extendForOutpainting && extendForOutpainting.value == true) { toggleWidget(node, findWidgetByName(node, "extend_up_factor"), true); toggleWidget(node, findWidgetByName(node, "extend_down_factor"), true); toggleWidget(node, findWidgetByName(node, "extend_left_factor"), true); @@ -38,7 +30,8 @@ function inpaintCropAndStitchHandler(node) { } toggleWidget(node, findWidgetByName(node, "output_target_width")); toggleWidget(node, findWidgetByName(node, "output_target_height")); - if (findWidgetByName(node, "output_resize_to_target_size").value == true) { + const outputResize = findWidgetByName(node, "output_resize_to_target_size"); + if (outputResize && outputResize.value == true) { toggleWidget(node, findWidgetByName(node, "output_target_width"), true); toggleWidget(node, findWidgetByName(node, "output_target_height"), true); } @@ -54,18 +47,19 @@ function inpaintCropAndStitchHandler(node) { toggleWidget(node, findWidgetByName(node, "max_width")); toggleWidget(node, findWidgetByName(node, "max_height")); toggleWidget(node, findWidgetByName(node, "padding")); - if (findWidgetByName(node, "mode").value == "free size") { + const mode = findWidgetByName(node, "mode"); + if (mode && mode.value == "free size") { toggleWidget(node, findWidgetByName(node, "rescale_factor"), true); toggleWidget(node, findWidgetByName(node, "padding"), true); } - else if (findWidgetByName(node, "mode").value == "ranged size") { + else if (mode && mode.value == "ranged size") { toggleWidget(node, findWidgetByName(node, "min_width"), true); toggleWidget(node, findWidgetByName(node, "min_height"), true); toggleWidget(node, findWidgetByName(node, "max_width"), true); toggleWidget(node, findWidgetByName(node, "max_height"), true); toggleWidget(node, findWidgetByName(node, "padding"), true); } - else if (findWidgetByName(node, "mode").value == "forced size") { + else if (mode && mode.value == "forced size") { toggleWidget(node, findWidgetByName(node, "force_width"), true); toggleWidget(node, findWidgetByName(node, "force_height"), true); } @@ -78,13 +72,14 @@ function inpaintCropAndStitchHandler(node) { toggleWidget(node, findWidgetByName(node, "expand_left_factor")); toggleWidget(node, findWidgetByName(node, "expand_right_pixels")); toggleWidget(node, findWidgetByName(node, "expand_right_factor")); - if (findWidgetByName(node, "mode").value == "factors") { + const mode = findWidgetByName(node, "mode"); + if (mode && mode.value == "factors") { toggleWidget(node, findWidgetByName(node, "expand_up_factor"), true); toggleWidget(node, findWidgetByName(node, "expand_down_factor"), true); toggleWidget(node, findWidgetByName(node, "expand_left_factor"), true); toggleWidget(node, findWidgetByName(node, "expand_right_factor"), true); } - if (findWidgetByName(node, "mode").value == "pixels") { + if (mode && mode.value == "pixels") { toggleWidget(node, findWidgetByName(node, "expand_up_pixels"), true); toggleWidget(node, findWidgetByName(node, "expand_down_pixels"), true); toggleWidget(node, findWidgetByName(node, "expand_left_pixels"), true); @@ -94,11 +89,12 @@ function inpaintCropAndStitchHandler(node) { toggleWidget(node, findWidgetByName(node, "min_width")); toggleWidget(node, findWidgetByName(node, "min_height")); toggleWidget(node, findWidgetByName(node, "rescale_factor")); - if (findWidgetByName(node, "mode").value == "ensure minimum size") { + const mode = findWidgetByName(node, "mode"); + if (mode && mode.value == "ensure minimum size") { toggleWidget(node, findWidgetByName(node, "min_width"), true); toggleWidget(node, findWidgetByName(node, "min_height"), true); } - else if (findWidgetByName(node, "mode").value == "factor") { + else if (mode && mode.value == "factor") { toggleWidget(node, findWidgetByName(node, "rescale_factor"), true); } } @@ -112,48 +108,78 @@ const findWidgetByName = (node, name) => { // Toggle Widget + change size function toggleWidget(node, widget, show = false, suffix = "") { if (!widget) return; - widget.disabled = !show + widget.disabled = !show; + if (widget.options) { + widget.options.disabled = !show; + } + if (widget._state) { + widget._state.disabled = !show; + } widget.linkedWidgets?.forEach(w => toggleWidget(node, w, ":" + widget.name, show)); -} +} + +function getPropertyDescriptor(obj, prop) { + let current = obj; + while (current) { + const desc = Object.getOwnPropertyDescriptor(current, prop); + if (desc) return desc; + current = Object.getPrototypeOf(current); + } + return null; +} app.registerExtension({ name: "inpaint-cropandstitch.showcontrol", nodeCreated(node) { - if (!node.comfyClass.startsWith("Inpaint")) { + if (!node.comfyClass || !node.comfyClass.startsWith("Inpaint")) { return; } - inpaintCropAndStitchHandler(node); + const origOnConfigure = node.onConfigure; + node.onConfigure = function() { + const res = origOnConfigure?.apply(this, arguments); + inpaintCropAndStitchHandler(this); + return res; + }; + for (const w of node.widgets || []) { let widgetValue = w.value; - - // Store the original descriptor if it exists - let originalDescriptor = Object.getOwnPropertyDescriptor(w, 'value') || - Object.getOwnPropertyDescriptor(Object.getPrototypeOf(w), 'value'); - if (!originalDescriptor) { - originalDescriptor = Object.getOwnPropertyDescriptor(w.constructor.prototype, 'value'); - } + const originalDescriptor = getPropertyDescriptor(w, 'value'); Object.defineProperty(w, 'value', { get() { - // If there's an original getter, use it. Otherwise, return widgetValue. let valueToReturn = originalDescriptor && originalDescriptor.get - ? originalDescriptor.get.call(w) + ? originalDescriptor.get.call(this) : widgetValue; return valueToReturn; }, set(newVal) { - // If there's an original setter, use it. Otherwise, set widgetValue. if (originalDescriptor && originalDescriptor.set) { - originalDescriptor.set.call(w, newVal); + originalDescriptor.set.call(this, newVal); } else { widgetValue = newVal; } inpaintCropAndStitchHandler(node); - } + }, + configurable: true, + enumerable: true }); + + const origCallback = w.callback; + w.callback = function() { + const res = origCallback?.apply(this, arguments); + inpaintCropAndStitchHandler(node); + return res; + }; + } + + inpaintCropAndStitchHandler(node); + }, + loadedGraphNode(node) { + if (node.comfyClass && node.comfyClass.startsWith("Inpaint")) { + inpaintCropAndStitchHandler(node); } } }); diff --git a/pyproject.toml b/pyproject.toml index 71c0792..6004392 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "comfyui-inpaint-cropandstitch" description = "The '✂️ Inpaint Crop' and '✂️ Inpaint Stitch' nodes enable inpainting only on masked area very easily: crop the image around the masked area with the Crop node, then use any standard workflow for sampling, then connect the sampled image to the Stitch node, which will put it back in place in the original image. These nodes enable faster sampling of smaller areas and take care of downsampling and upsampling to fit specific model and resource needs." -version = "3.0.13" +version = "3.0.14" license = { file = "LICENSE" } [project.urls]