Skip to content

Commit 432ba1c

Browse files
Merge branch 'control_before_generate' of https://github.com/pythongosssss/ComfyUI
2 parents b5ece63 + 8e91673 commit 432ba1c

File tree

2 files changed

+73
-2
lines changed

2 files changed

+73
-2
lines changed

web/scripts/app.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { ComfyLogging } from "./logging.js";
2-
import { ComfyWidgets } from "./widgets.js";
2+
import { ComfyWidgets, initWidgets } from "./widgets.js";
33
import { ComfyUI, $el } from "./ui.js";
44
import { api } from "./api.js";
55
import { defaultGraph } from "./defaultGraph.js";
@@ -1420,6 +1420,7 @@ export class ComfyApp {
14201420

14211421
await this.#invokeExtensionsAsync("init");
14221422
await this.registerNodes();
1423+
initWidgets(this);
14231424

14241425
// Load previous workflow
14251426
let restored = false;
@@ -1774,6 +1775,14 @@ export class ComfyApp {
17741775
*/
17751776
async graphToPrompt() {
17761777
for (const outerNode of this.graph.computeExecutionOrder(false)) {
1778+
if (outerNode.widgets) {
1779+
for (const widget of outerNode.widgets) {
1780+
// Allow widgets to run callbacks before a prompt has been queued
1781+
// e.g. random seed before every gen
1782+
widget.beforeQueued?.();
1783+
}
1784+
}
1785+
17771786
const innerNodes = outerNode.getInnerNodes ? outerNode.getInnerNodes() : [outerNode];
17781787
for (const node of innerNodes) {
17791788
if (node.isVirtualNode) {

web/scripts/widgets.js

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,19 @@
11
import { api } from "./api.js"
22
import "./domWidget.js";
33

4+
let controlValueRunBefore = false;
5+
export function updateControlWidgetLabel(widget) {
6+
let replacement = "after";
7+
let find = "before";
8+
if (controlValueRunBefore) {
9+
[find, replacement] = [replacement, find]
10+
}
11+
widget.label = (widget.label ?? widget.name).replace(find, replacement);
12+
}
13+
14+
const IS_CONTROL_WIDGET = Symbol();
15+
const HAS_EXECUTED = Symbol();
16+
417
function getNumberDefaults(inputData, defaultStep, precision, enable_rounding) {
518
let defaultVal = inputData[1]["default"];
619
let { min, max, step, round} = inputData[1];
@@ -62,6 +75,8 @@ export function addValueControlWidgets(node, targetWidget, defaultValue = "rando
6275
serialize: false, // Don't include this in prompt.
6376
}
6477
);
78+
valueControl[IS_CONTROL_WIDGET] = true;
79+
updateControlWidgetLabel(valueControl);
6580
widgets.push(valueControl);
6681

6782
const isCombo = targetWidget.type === "combo";
@@ -76,10 +91,12 @@ export function addValueControlWidgets(node, targetWidget, defaultValue = "rando
7691
serialize: false, // Don't include this in prompt.
7792
}
7893
);
94+
updateControlWidgetLabel(comboFilter);
95+
7996
widgets.push(comboFilter);
8097
}
8198

82-
valueControl.afterQueued = () => {
99+
const applyWidgetControl = () => {
83100
var v = valueControl.value;
84101

85102
if (isCombo && v !== "fixed") {
@@ -159,6 +176,23 @@ export function addValueControlWidgets(node, targetWidget, defaultValue = "rando
159176
targetWidget.callback(targetWidget.value);
160177
}
161178
};
179+
180+
valueControl.beforeQueued = () => {
181+
if (controlValueRunBefore) {
182+
// Don't run on first execution
183+
if (valueControl[HAS_EXECUTED]) {
184+
applyWidgetControl();
185+
}
186+
}
187+
valueControl[HAS_EXECUTED] = true;
188+
};
189+
190+
valueControl.afterQueued = () => {
191+
if (!controlValueRunBefore) {
192+
applyWidgetControl();
193+
}
194+
};
195+
162196
return widgets;
163197
};
164198

@@ -224,6 +258,34 @@ function isSlider(display, app) {
224258
return (display==="slider") ? "slider" : "number"
225259
}
226260

261+
export function initWidgets(app) {
262+
app.ui.settings.addSetting({
263+
id: "Comfy.WidgetControlMode",
264+
name: "Widget Value Control Mode",
265+
type: "combo",
266+
defaultValue: "after",
267+
options: ["before", "after"],
268+
tooltip: "Controls when widget values are updated (randomize/increment/decrement), either before the prompt is queued or after.",
269+
onChange(value) {
270+
controlValueRunBefore = value === "before";
271+
for (const n of app.graph._nodes) {
272+
if (!n.widgets) continue;
273+
for (const w of n.widgets) {
274+
if (w[IS_CONTROL_WIDGET]) {
275+
updateControlWidgetLabel(w);
276+
if (w.linkedWidgets) {
277+
for (const l of w.linkedWidgets) {
278+
updateControlWidgetLabel(l);
279+
}
280+
}
281+
}
282+
}
283+
}
284+
app.graph.setDirtyCanvas(true);
285+
},
286+
});
287+
}
288+
227289
export const ComfyWidgets = {
228290
"INT:seed": seedWidget,
229291
"INT:noise_seed": seedWidget,

0 commit comments

Comments
 (0)