72 lines
3.1 KiB
JavaScript
72 lines
3.1 KiB
JavaScript
import { app } from "../../scripts/app.js";
|
|
|
|
const nodeNames = new Set(["KIE_GPTImage2_TextToImage", "KIE_GPTImage2_ImageToImage"]);
|
|
const definitions = new Map();
|
|
|
|
function syncOptions(node, normalize = false) {
|
|
const rules = definitions.get(node.comfyClass);
|
|
if (!rules) return;
|
|
const widgets = Object.fromEntries((node.widgets ?? []).map((widget) => [widget.name, widget]));
|
|
const isLinked = (name) => node.inputs?.some((input) => input.name === name && input.link != null);
|
|
// A connected selector is unknown until execution: offer the union of valid choices.
|
|
const candidates = isLinked("model") ? Object.values(rules) : [rules[widgets.model?.value]];
|
|
if (candidates.some((options) => !options)) return;
|
|
const union = (values) => [...new Set(values.flat())];
|
|
const update = (name, values) => {
|
|
const widget = widgets[name];
|
|
if (!widget || !values || isLinked(name)) return;
|
|
widget.options.values = [...values];
|
|
if (normalize && !values.includes(widget.value)) {
|
|
widget.value = values[0];
|
|
widget.callback?.(widget.value);
|
|
}
|
|
};
|
|
update("aspect_ratio", union(candidates.map((options) => options.aspect_ratios)));
|
|
const resolutions = union(candidates.flatMap((options) => isLinked("aspect_ratio")
|
|
? Object.values(options.resolutions)
|
|
: [options.resolutions[widgets.aspect_ratio?.value] ?? []]));
|
|
if (resolutions.length) update("resolution", resolutions);
|
|
update("background", union(candidates.map((options) => options.backgrounds)));
|
|
node.setDirtyCanvas?.(true, true);
|
|
}
|
|
|
|
app.registerExtension({
|
|
name: "KIE.GPTImageOptions",
|
|
beforeRegisterNodeDef(_nodeType, nodeData) {
|
|
if (nodeNames.has(nodeData.name)) {
|
|
definitions.set(nodeData.name, nodeData.input.optional.model[1].kie_model_options);
|
|
}
|
|
},
|
|
nodeCreated(node) {
|
|
if (!nodeNames.has(node.comfyClass)) return;
|
|
const onConfigure = node.onConfigure;
|
|
node.onConfigure = function (...args) {
|
|
const result = onConfigure?.apply(this, args);
|
|
// Covers clone/paste as well as full graph loading, without rewriting values.
|
|
syncOptions(this);
|
|
return result;
|
|
};
|
|
const onConnectionsChange = node.onConnectionsChange;
|
|
node.onConnectionsChange = function (...args) {
|
|
const result = onConnectionsChange?.apply(this, args);
|
|
// Wait for connection bookkeeping to finish before reading link state.
|
|
queueMicrotask(() => syncOptions(this));
|
|
return result;
|
|
};
|
|
for (const widget of node.widgets ?? []) {
|
|
if (!["model", "aspect_ratio"].includes(widget.name)) continue;
|
|
const original = widget.callback;
|
|
widget.callback = function (...args) {
|
|
const result = original?.apply(this, args);
|
|
syncOptions(node, true);
|
|
return result;
|
|
};
|
|
}
|
|
syncOptions(node);
|
|
},
|
|
loadedGraphNode(node) {
|
|
// Never silently rewrite a saved workflow's parameters on load.
|
|
syncOptions(node);
|
|
},
|
|
});
|