|
|
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") {
|
|
|
node.inputs = [{ ...input, name: inputName }];
|
|
|
node.widgets = [];
|
|
|
} else {
|
|
|
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 };
|
|
|
};
|
|
|
}
|
|
|
});
|
|
|
|