bobinamoe's picture
Upload 1664 files
baac5bb verified
import { app } from "../../scripts/app.js";
function mimicNode(node, target, slot) {
const getWidget = (widget) => {
if (typeof widget.origType === "undefined") return widget;
const newWidget = new Proxy(widget, {
has(target, prop) {
return prop in target && prop !== "origType" && prop !== "computeSize";
},
get(target, prop) {
if (prop.startsWith("orig") || prop === "computeSize") {
return undefined;
} else if (prop === "type") {
return target.origType;
} else if (prop === "name") {
return inputName;
} else {
return target[prop];
}
},
set(target, prop, value) {
target[prop] = value;
return true;
}
});
return newWidget;
}
const input = target.inputs[slot];
const inputName = node.inputs.length > 0 ? node.inputs[0].name : node.widgets[0].name;
if (typeof input.widget === "undefined") { // This is an input
node.inputs = [{ ...input, name: inputName }];
node.widgets = [];
} else { // This is a widget
node.widgets = [getWidget(target.widgets.find(w => w.name === input.name))];
node.inputs = [];
node.size = node.computeSize();
requestAnimationFrame(() => {
if (node.onResize) {
node.onResize(node.size);
}
});
}
}
app.registerExtension({
name: "Comfy.DynamicInput",
dynamicNodes: ["CPackInputAny", "CPackInputFile"],
async beforeRegisterNodeDef(nodeType, nodeData) {
if (!this.dynamicNodes.includes(nodeData.name)) return;
nodeType.prototype.onConnectOutput = function () {
if (this.outputs[0].links?.length > 0) return false;
const target = arguments[3];
if (this.type === "CPackInputFile" && !["COMBO", "STRING"].includes(target.inputs[arguments[4]].type))
return false;
mimicNode(this, target, arguments[4]);
this.title = target.inputs[arguments[4]].name;
}
},
async setup(app) {
app.graph.nodes.forEach((node) => {
if (!this.dynamicNodes.includes(node.type)) return;
if (node.outputs.length > 0 && node.outputs[0].links.length > 0) {
const link = node.graph.links[node.outputs[0].links[0]];
mimicNode(node, app.graph.getNodeById(link.target_id), link.target_slot);
}
})
},
async init(app) {
const originalToPrompt = app.graphToPrompt;
const self = this;
app.graphToPrompt = async function(graph = app.graph, clean = true) {
const { workflow, output } = await originalToPrompt(graph, clean);
Object.entries(output).forEach(([id, nodeData]) => {
if (!nodeData.class_type.startsWith("CPackInput")) return;
const node = graph.getNodeById(parseInt(id));
if (!nodeData["_meta"]) {
nodeData["_meta"] = { title: node.title };
}
if (node.widgets.length === 0) return;
const widget = node.widgets[0];
nodeData["_meta"] = { ...nodeData["_meta"], options: widget.options };
});
return { workflow, output };
};
}
});