diff --git a/web/extensions/core/widgetInputs.js b/web/extensions/core/widgetInputs.js index ff9227d28..06975f503 100644 --- a/web/extensions/core/widgetInputs.js +++ b/web/extensions/core/widgetInputs.js @@ -285,7 +285,7 @@ app.registerExtension({ } if (widget.type === "number") { - addRandomizeWidget(this, widget, "Random after every gen"); + addRandomizeWidget(this, widget, "randomize", "off"); } // When our value changes, update other widgets to reflect our changes diff --git a/web/scripts/app.js b/web/scripts/app.js index a743ef63b..0b5a37d14 100644 --- a/web/scripts/app.js +++ b/web/scripts/app.js @@ -653,6 +653,23 @@ class ComfyApp { // Patch T2IAdapterLoader to ControlNetLoader since they are the same node now for (let n of graphData.nodes) { if (n.type == "T2IAdapterLoader") n.type = "ControlNetLoader"; + + // Convert old random settings to new ones. + // true -> "after generation" + // false -> "off" + if (n.type === "KSampler" || n.type === "KSamplerAdvanced" || n.type === "PrimitiveNode") { + // KSampler and PrimitiveNode have the random setting as the second widget. + // KSamplerAdvanced has it as the third widget. + let randomWidgetIndex = 1; + if (n.type === "KSamplerAdvanced") randomWidgetIndex = 2; + + const randomSetting = n.widgets_values[randomWidgetIndex]; + if (randomSetting === true) { + n.widgets_values[randomWidgetIndex] = "after generation"; + } else if (randomSetting !== "before generation") { + n.widgets_values[randomWidgetIndex] = "off"; + } + } } this.graph.configure(graphData); @@ -744,7 +761,22 @@ class ComfyApp { async queuePrompt(number, batchCount = 1) { for (let i = 0; i < batchCount; i++) { - const p = await this.graphToPrompt(); + let p = await this.graphToPrompt(); + + for (const n of p.workflow.nodes) { + const node = graph.getNodeById(n.id); + if (node.widgets) { + for (const widget of node.widgets) { + // Allow widgets to run callbacks before a prompt has been queued + // e.g. random seed before every gen + if (widget.beforeQueued) { + widget.beforeQueued(); + } + } + } + } + + p = await this.graphToPrompt(); try { await api.queuePrompt(number, p); diff --git a/web/scripts/defaultGraph.js b/web/scripts/defaultGraph.js index 967377ad6..ed0f66066 100644 --- a/web/scripts/defaultGraph.js +++ b/web/scripts/defaultGraph.js @@ -56,7 +56,7 @@ export const defaultGraph = { ], outputs: [{ name: "LATENT", type: "LATENT", links: [7], slot_index: 0 }], properties: {}, - widgets_values: [8566257, true, 20, 8, "euler", "normal", 1], + widgets_values: [8566257, "after generation", 20, 8, "euler", "normal", 1], }, { id: 8, diff --git a/web/scripts/widgets.js b/web/scripts/widgets.js index 5f5043cd0..fe54e7d38 100644 --- a/web/scripts/widgets.js +++ b/web/scripts/widgets.js @@ -11,33 +11,45 @@ function getNumberDefaults(inputData, defaultStep) { } export function addRandomizeWidget(node, targetWidget, name, defaultValue = false) { - const randomize = node.addWidget("toggle", name, defaultValue, function (v) {}, { - on: "enabled", - off: "disabled", + const randomize = node.addWidget("combo", name, defaultValue, function (v) {}, { + values: ["after generation", "before generation", "off"], serialize: false, // Don't include this in prompt. }); - randomize.afterQueued = () => { - if (randomize.value) { - const min = targetWidget.options?.min; - let max = targetWidget.options?.max; - if (min != null || max != null) { - if (max) { - // limit max to something that javascript can handle - max = Math.min(1125899906842624, max); - } - targetWidget.value = Math.floor(Math.random() * ((max ?? 9999999999) - (min ?? 0) + 1) + (min ?? 0)); - } else { - targetWidget.value = Math.floor(Math.random() * 1125899906842624); + const generateSeed = () => { + const min = targetWidget.options?.min; + let max = targetWidget.options?.max; + if (min != null || max != null) { + if (max) { + // limit max to something that javascript can handle + max = Math.min(1125899906842624, max); } + targetWidget.value = Math.floor(Math.random() * ((max ?? 9999999999) - (min ?? 0) + 1) + (min ?? 0)); + } else { + targetWidget.value = Math.floor(Math.random() * 1125899906842624); } }; + + randomize.beforeQueued = () => { + if (randomize.value === "before generation") { + generateSeed() + } + }; + + randomize.afterQueued = () => { + // Check if value is true for backward compatibilty with the previous toggle + // version of this widget. + if (randomize.value === "after generation" || randomize.value === true) { + generateSeed() + } + }; + return randomize; } function seedWidget(node, inputName, inputData) { const seed = ComfyWidgets.INT(node, inputName, inputData); - const randomize = addRandomizeWidget(node, seed.widget, "Random seed after every gen", true); + const randomize = addRandomizeWidget(node, seed.widget, "random seed", "after generation"); seed.widget.linkedWidgets = [randomize]; return { widget: seed, randomize };