mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2026-02-12 22:42:36 +08:00
fix naming
allow control_after_generate custom name allow convert from reroutes
This commit is contained in:
parent
323c3107c8
commit
f17333ca4b
@ -52,16 +52,13 @@ function buildNodeDef(config, nodeName, defs, workflow) {
|
|||||||
};
|
};
|
||||||
const links = getLinks(config);
|
const links = getLinks(config);
|
||||||
|
|
||||||
console.log(
|
const seenInputs = {};
|
||||||
"Building group node",
|
const seenOutputs = {};
|
||||||
nodeName,
|
|
||||||
config.nodes.map((n) => n.type)
|
|
||||||
);
|
|
||||||
|
|
||||||
let inputCount = 0;
|
let inputCount = 0;
|
||||||
for (let nodeId = 0; nodeId < config.nodes.length; nodeId++) {
|
for (let nodeId = 0; nodeId < config.nodes.length; nodeId++) {
|
||||||
const node = config.nodes[nodeId];
|
const node = config.nodes[nodeId];
|
||||||
console.log("Processing inner node", nodeId, node.type);
|
// console.info("Processing inner node", nodeId, node.type);
|
||||||
let def = defs[node.type];
|
let def = defs[node.type];
|
||||||
|
|
||||||
const linksTo = links.linksTo[nodeId];
|
const linksTo = links.linksTo[nodeId];
|
||||||
@ -73,6 +70,7 @@ function buildNodeDef(config, nodeName, defs, workflow) {
|
|||||||
if (linksTo && linksFrom) {
|
if (linksTo && linksFrom) {
|
||||||
// Being used internally
|
// Being used internally
|
||||||
// TODO: does anything actually need doing here?
|
// TODO: does anything actually need doing here?
|
||||||
|
debugger;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,8 +103,7 @@ function buildNodeDef(config, nodeName, defs, workflow) {
|
|||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
// Front end only node
|
// Front end only node
|
||||||
// TODO: check these should all be ignored
|
console.warn("Skipping virtual node " + node.type + " when building group node " + nodeName);
|
||||||
debugger;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -118,11 +115,27 @@ function buildNodeDef(config, nodeName, defs, workflow) {
|
|||||||
let linkInputId = 0;
|
let linkInputId = 0;
|
||||||
for (let inputId = 0; inputId < inputNames.length; inputId++) {
|
for (let inputId = 0; inputId < inputNames.length; inputId++) {
|
||||||
const inputName = inputNames[inputId];
|
const inputName = inputNames[inputId];
|
||||||
console.log("\t", "> Processing input", inputId, inputName);
|
// console.info("\t", "> Processing input", inputId, inputName);
|
||||||
const widgetType = getWidgetType(inputs[inputName], inputName);
|
const widgetType = getWidgetType(inputs[inputName], inputName);
|
||||||
let name = nodeId + ":" + inputName;
|
let prefix = node.title ?? node.type;
|
||||||
|
let name = `${prefix} ${inputName}`;
|
||||||
|
|
||||||
|
if (name in seenInputs) {
|
||||||
|
prefix = `${node.title ?? node.type} ${++seenInputs[name]}`;
|
||||||
|
name = `${prefix} ${inputName}`;
|
||||||
|
} else {
|
||||||
|
seenInputs[name] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nodeInput = node.inputs?.findIndex((input) => input.name === inputName);
|
||||||
|
|
||||||
|
// For now internal widget inputs are not supported
|
||||||
|
if (nodeInput > -1 && node.inputs[nodeInput]?.widget) {
|
||||||
|
node.inputs.splice(nodeInput, 1);
|
||||||
|
}
|
||||||
|
|
||||||
if (widgetType) {
|
if (widgetType) {
|
||||||
console.log("\t\t", "Widget", widgetType);
|
// console.info("\t\t", "Widget", widgetType);
|
||||||
|
|
||||||
// Store mapping to get a group widget name from an inner id + name
|
// Store mapping to get a group widget name from an inner id + name
|
||||||
if (!slots.widgets[nodeId]) slots.widgets[nodeId] = {};
|
if (!slots.widgets[nodeId]) slots.widgets[nodeId] = {};
|
||||||
@ -130,11 +143,11 @@ function buildNodeDef(config, nodeName, defs, workflow) {
|
|||||||
} else {
|
} else {
|
||||||
if (linksTo?.[linkInputId]) {
|
if (linksTo?.[linkInputId]) {
|
||||||
linkInputId++;
|
linkInputId++;
|
||||||
console.info("\t\t", "Link skipped as has internal connection");
|
// console.info("\t\t", "Link skipped as has internal connection");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.info("\t\t", "Link", linkInputId + " -> outer input " + inputCount);
|
// console.info("\t\t", "Link", linkInputId + " -> outer input " + inputCount);
|
||||||
|
|
||||||
// Store a mapping to let us get the group node input for a specific slot on an inner node
|
// Store a mapping to let us get the group node input for a specific slot on an inner node
|
||||||
if (!slots.inputs[nodeId]) slots.inputs[nodeId] = {};
|
if (!slots.inputs[nodeId]) slots.inputs[nodeId] = {};
|
||||||
@ -144,17 +157,17 @@ function buildNodeDef(config, nodeName, defs, workflow) {
|
|||||||
let inputDef = inputs[inputName];
|
let inputDef = inputs[inputName];
|
||||||
if (inputName === "seed" || inputName === "noise_seed") {
|
if (inputName === "seed" || inputName === "noise_seed") {
|
||||||
inputDef = [...inputDef];
|
inputDef = [...inputDef];
|
||||||
inputDef[1] = { control_after_generate: true, ...inputDef[1] };
|
inputDef[1] = { control_after_generate: `${prefix} control_after_generate`, ...inputDef[1] };
|
||||||
}
|
}
|
||||||
newDef.input.required[name] = inputDef;
|
newDef.input.required[name] = inputDef;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add outputs
|
// Add outputs
|
||||||
for (let outputId = 0; outputId < def.output.length; outputId++) {
|
for (let outputId = 0; outputId < def.output.length; outputId++) {
|
||||||
console.log("\t", "< Processing output", outputId, def.output_name?.[outputId] ?? def.output[outputId]);
|
// console.info("\t", "< Processing output", outputId, def.output_name?.[outputId] ?? def.output[outputId]);
|
||||||
|
|
||||||
if (linksFrom?.[outputId]) {
|
if (linksFrom?.[outputId]) {
|
||||||
console.info("\t\t", "Skipping as has internal connection");
|
// console.info("\t\t", "Skipping as has internal connection");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,7 +178,17 @@ function buildNodeDef(config, nodeName, defs, workflow) {
|
|||||||
|
|
||||||
newDef.output.push(def.output[outputId]);
|
newDef.output.push(def.output[outputId]);
|
||||||
newDef.output_is_list.push(def.output_is_list[outputId]);
|
newDef.output_is_list.push(def.output_is_list[outputId]);
|
||||||
newDef.output_name.push(nodeId + ":" + (def.output_name?.[outputId] ?? def.output[outputId]));
|
|
||||||
|
const label = def.output_name?.[outputId] ?? def.output[outputId];
|
||||||
|
let name = `${node.title ?? node.type} ${label}`;
|
||||||
|
|
||||||
|
if (name in seenOutputs) {
|
||||||
|
name = `${node.title ?? node.type} ${++seenOutputs[name]} ${label}`;
|
||||||
|
} else {
|
||||||
|
seenOutputs[name] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
newDef.output_name.push(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -277,6 +300,7 @@ class ConvertToGroupAction {
|
|||||||
this.linkInputs(newNode, config, slots);
|
this.linkInputs(newNode, config, slots);
|
||||||
|
|
||||||
newNode.pos = [left, top];
|
newNode.pos = [left, top];
|
||||||
|
return newNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
addOption(options, index) {
|
addOption(options, index) {
|
||||||
@ -295,7 +319,7 @@ class ConvertToGroupAction {
|
|||||||
const { config, def } = await this.register(name);
|
const { config, def } = await this.register(name);
|
||||||
groupNodes[name] = config;
|
groupNodes[name] = config;
|
||||||
|
|
||||||
this.convert(name, config, def);
|
return this.convert(name, config, def);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -306,9 +330,9 @@ let globalDefs;
|
|||||||
const ext = {
|
const ext = {
|
||||||
name: id,
|
name: id,
|
||||||
setup() {
|
setup() {
|
||||||
const orig = LGraphCanvas.prototype.getCanvasMenuOptions;
|
const getCanvasMenuOptions = LGraphCanvas.prototype.getCanvasMenuOptions;
|
||||||
LGraphCanvas.prototype.getCanvasMenuOptions = function () {
|
LGraphCanvas.prototype.getCanvasMenuOptions = function () {
|
||||||
const options = orig.apply(this, arguments);
|
const options = getCanvasMenuOptions.apply(this, arguments);
|
||||||
new ConvertToGroupAction().addOption(options, options.length);
|
new ConvertToGroupAction().addOption(options, options.length);
|
||||||
return options;
|
return options;
|
||||||
};
|
};
|
||||||
@ -334,13 +358,37 @@ const ext = {
|
|||||||
const split = detail.node.split(":");
|
const split = detail.node.split(":");
|
||||||
if (split.length === 2) {
|
if (split.length === 2) {
|
||||||
const outerNode = app.graph.getNodeById(+split[0]);
|
const outerNode = app.graph.getNodeById(+split[0]);
|
||||||
if(outerNode?.constructor.nodeData?.[IS_GROUP_NODE]) {
|
if (outerNode?.constructor.nodeData?.[IS_GROUP_NODE]) {
|
||||||
api.dispatchEvent(new CustomEvent("executed", { detail: { ...detail, node: split[0], merge: !outerNode.resetExecution } }));
|
api.dispatchEvent(
|
||||||
|
new CustomEvent("executed", { detail: { ...detail, node: split[0], merge: !outerNode.resetExecution } })
|
||||||
|
);
|
||||||
outerNode.resetExecution = false;
|
outerNode.resetExecution = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Attach handlers after everything is registered to ensure all nodes are found
|
||||||
|
for (const k in LiteGraph.registered_node_types) {
|
||||||
|
const nodeType = LiteGraph.registered_node_types[k];
|
||||||
|
|
||||||
|
if (nodeType.nodeData?.[IS_GROUP_NODE]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const getExtraMenuOptions = nodeType.prototype.getExtraMenuOptions;
|
||||||
|
nodeType.prototype.getExtraMenuOptions = function (_, options) {
|
||||||
|
const r = getExtraMenuOptions?.apply?.(this, arguments);
|
||||||
|
|
||||||
|
let i = options.findIndex((o) => o.content === "Outputs");
|
||||||
|
if (i === -1) i = options.length;
|
||||||
|
else i++;
|
||||||
|
|
||||||
|
new ConvertToGroupAction().addOption(options, i);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
};
|
||||||
|
}
|
||||||
},
|
},
|
||||||
async beforeConfigureGraph(graphData) {
|
async beforeConfigureGraph(graphData) {
|
||||||
const groupNodes = graphData?.extra?.groupNodes;
|
const groupNodes = graphData?.extra?.groupNodes;
|
||||||
@ -361,10 +409,10 @@ const ext = {
|
|||||||
const slots = def[GROUP_SLOTS];
|
const slots = def[GROUP_SLOTS];
|
||||||
|
|
||||||
const onExecutionStart = node.onExecutionStart;
|
const onExecutionStart = node.onExecutionStart;
|
||||||
node.onExecutionStart = function() {
|
node.onExecutionStart = function () {
|
||||||
node.resetExecution = true;
|
node.resetExecution = true;
|
||||||
return onExecutionStart?.apply(this, arguments);
|
return onExecutionStart?.apply(this, arguments);
|
||||||
}
|
};
|
||||||
|
|
||||||
const onNodeCreated = node.onNodeCreated;
|
const onNodeCreated = node.onNodeCreated;
|
||||||
node.onNodeCreated = function () {
|
node.onNodeCreated = function () {
|
||||||
@ -418,8 +466,10 @@ const ext = {
|
|||||||
let top;
|
let top;
|
||||||
let left;
|
let left;
|
||||||
const selectedIds = Object.keys(app.canvas.selected_nodes);
|
const selectedIds = Object.keys(app.canvas.selected_nodes);
|
||||||
|
const newNodes = [];
|
||||||
for (const id of selectedIds) {
|
for (const id of selectedIds) {
|
||||||
const newNode = app.graph.getNodeById(id);
|
const newNode = app.graph.getNodeById(id);
|
||||||
|
newNodes.push(newNode);
|
||||||
if (left == null || newNode.pos[0] < left) {
|
if (left == null || newNode.pos[0] < left) {
|
||||||
left = newNode.pos[0];
|
left = newNode.pos[0];
|
||||||
}
|
}
|
||||||
@ -465,6 +515,7 @@ const ext = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
app.graph.remove(this);
|
app.graph.remove(this);
|
||||||
|
return newNodes;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -488,7 +539,7 @@ const ext = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
node.getInnerNodes = function () {
|
node.getInnerNodes = function () {
|
||||||
console.log("Expanding group node", this.comfyClass, this.id);
|
// console.info("Expanding group node", this.comfyClass, this.id);
|
||||||
const links = getLinks(config);
|
const links = getLinks(config);
|
||||||
|
|
||||||
const innerNodes = config.nodes.map((n, i) => {
|
const innerNodes = config.nodes.map((n, i) => {
|
||||||
@ -499,7 +550,7 @@ const ext = {
|
|||||||
const groupWidgetName = slots.widgets[i][innerWidget.name];
|
const groupWidgetName = slots.widgets[i][innerWidget.name];
|
||||||
const groupWidget = node.widgets.find((w) => w.name === groupWidgetName);
|
const groupWidget = node.widgets.find((w) => w.name === groupWidgetName);
|
||||||
if (groupWidget) {
|
if (groupWidget) {
|
||||||
console.log("Set widget value", groupWidgetName + " -> " + innerWidget.name, groupWidget.value);
|
// console.info("Set widget value", groupWidgetName + " -> " + innerWidget.name, groupWidget.value);
|
||||||
innerWidget.value = groupWidget.value;
|
innerWidget.value = groupWidget.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -507,30 +558,32 @@ const ext = {
|
|||||||
innerNode.id = node.id + ":" + i;
|
innerNode.id = node.id + ":" + i;
|
||||||
innerNode.getInputNode = function (slot) {
|
innerNode.getInputNode = function (slot) {
|
||||||
if (!innerNode.comfyClass) slot = 0;
|
if (!innerNode.comfyClass) slot = 0;
|
||||||
console.log("Get input node", innerNode.comfyClass, slot, innerNode.inputs[slot]?.name);
|
// console.info("Get input node", innerNode.comfyClass, slot, innerNode.inputs?.[slot]?.name);
|
||||||
const outerSlot = slots.inputs[i]?.[slot];
|
const outerSlot = slots.inputs?.[i]?.[slot];
|
||||||
if (outerSlot != null) {
|
if (outerSlot != null) {
|
||||||
// Our inner node has a mapping to the group node inputs
|
// Our inner node has a mapping to the group node inputs
|
||||||
// return the input node from there
|
// return the input node from there
|
||||||
console.log("\t", "Getting from group node input", outerSlot);
|
// console.info("\t", "Getting from group node input", outerSlot);
|
||||||
const inputNode = node.getInputNode(outerSlot);
|
const inputNode = node.getInputNode(outerSlot);
|
||||||
console.log("\t", "Result", inputNode?.id, inputNode?.comfyClass);
|
// console.info("\t", "Result", inputNode?.id, inputNode?.comfyClass);
|
||||||
return inputNode;
|
return inputNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal link
|
// Internal link
|
||||||
const innerLink = links.linksTo[i][slot];
|
const innerLink = links.linksTo[i]?.[slot];
|
||||||
console.log("\t", "Internal link", innerLink);
|
if (!innerLink) return null;
|
||||||
|
|
||||||
|
// console.info("\t", "Internal link", innerLink);
|
||||||
const inputNode = innerNodes[innerLink[0]];
|
const inputNode = innerNodes[innerLink[0]];
|
||||||
console.log("\t", "Result", inputNode?.id, inputNode?.comfyClass);
|
// console.info("\t", "Result", inputNode?.id, inputNode?.comfyClass);
|
||||||
return inputNode;
|
return inputNode;
|
||||||
};
|
};
|
||||||
innerNode.getInputLink = function (slot) {
|
innerNode.getInputLink = function (slot) {
|
||||||
console.log("Get input link", innerNode.comfyClass, slot, innerNode.inputs[slot]?.name);
|
// console.info("Get input link", innerNode.comfyClass, slot, innerNode.inputs?.[slot]?.name);
|
||||||
const outerSlot = slots.inputs[i]?.[slot];
|
const outerSlot = slots.inputs[i]?.[slot];
|
||||||
if (outerSlot != null) {
|
if (outerSlot != null) {
|
||||||
// The inner node is connected via the group node inputs
|
// The inner node is connected via the group node inputs
|
||||||
console.log("\t", "Getting from group node input", outerSlot);
|
// console.info("\t", "Getting from group node input", outerSlot);
|
||||||
const linkId = node.inputs[outerSlot].link;
|
const linkId = node.inputs[outerSlot].link;
|
||||||
let link = app.graph.links[linkId];
|
let link = app.graph.links[linkId];
|
||||||
|
|
||||||
@ -540,11 +593,12 @@ const ext = {
|
|||||||
target_slot: slot,
|
target_slot: slot,
|
||||||
...link,
|
...link,
|
||||||
};
|
};
|
||||||
console.log("\t", "Result", link);
|
// console.info("\t", "Result", link);
|
||||||
return link;
|
return link;
|
||||||
}
|
}
|
||||||
|
|
||||||
let link = links.linksTo[i][slot];
|
let link = links.linksTo[i]?.[slot];
|
||||||
|
if (!link) return null;
|
||||||
// Use the inner link, but update the origin node to be inner node id
|
// Use the inner link, but update the origin node to be inner node id
|
||||||
link = {
|
link = {
|
||||||
origin_id: node.id + ":" + link[0],
|
origin_id: node.id + ":" + link[0],
|
||||||
@ -552,7 +606,7 @@ const ext = {
|
|||||||
target_id: node.id + ":" + i,
|
target_id: node.id + ":" + i,
|
||||||
target_slot: slot,
|
target_slot: slot,
|
||||||
};
|
};
|
||||||
console.log("\t", "Internal link", link);
|
// console.info("\t", "Internal link", link);
|
||||||
|
|
||||||
return link;
|
return link;
|
||||||
};
|
};
|
||||||
@ -564,17 +618,6 @@ const ext = {
|
|||||||
|
|
||||||
return innerNodes;
|
return innerNodes;
|
||||||
};
|
};
|
||||||
} else {
|
|
||||||
const getExtraMenuOptions = node.getExtraMenuOptions ?? node.prototype.getExtraMenuOptions;
|
|
||||||
node.getExtraMenuOptions = function (_, options) {
|
|
||||||
let i = options.findIndex((o) => o.content === "Outputs");
|
|
||||||
if (i === -1) i = options.length;
|
|
||||||
else i++;
|
|
||||||
|
|
||||||
new ConvertToGroupAction().addOption(options, i);
|
|
||||||
|
|
||||||
return getExtraMenuOptions.apply(this, arguments);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -36,12 +36,12 @@ export function getWidgetType(inputData, inputName) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function addValueControlWidget(node, targetWidget, defaultValue = "randomize", values) {
|
export function addValueControlWidget(node, targetWidget, defaultValue = "randomize", values, widgetName) {
|
||||||
const valueControl = node.addWidget("combo", "control_after_generate", defaultValue, function (v) { }, {
|
const valueControl = node.addWidget("combo", widgetName ?? "control_after_generate", defaultValue, function (v) {}, {
|
||||||
values: ["fixed", "increment", "decrement", "randomize"],
|
values: ["fixed", "increment", "decrement", "randomize"],
|
||||||
serialize: false, // Don't include this in prompt.
|
serialize: false, // Don't include this in prompt.
|
||||||
});
|
});
|
||||||
valueControl.afterQueued = () => {
|
valueControl.afterQueued = () => {
|
||||||
var v = valueControl.value;
|
var v = valueControl.value;
|
||||||
|
|
||||||
if (targetWidget.type == "combo" && v !== "fixed") {
|
if (targetWidget.type == "combo" && v !== "fixed") {
|
||||||
@ -67,7 +67,8 @@ export function addValueControlWidget(node, targetWidget, defaultValue = "random
|
|||||||
targetWidget.value = value;
|
targetWidget.value = value;
|
||||||
targetWidget.callback(value);
|
targetWidget.callback(value);
|
||||||
}
|
}
|
||||||
} else { //number
|
} else {
|
||||||
|
//number
|
||||||
let min = targetWidget.options.min;
|
let min = targetWidget.options.min;
|
||||||
let max = targetWidget.options.max;
|
let max = targetWidget.options.max;
|
||||||
// limit to something that javascript can handle
|
// limit to something that javascript can handle
|
||||||
@ -100,17 +101,18 @@ export function addValueControlWidget(node, targetWidget, defaultValue = "random
|
|||||||
return valueControl;
|
return valueControl;
|
||||||
}
|
}
|
||||||
|
|
||||||
function seedWidget(node, inputName, inputData, app) {
|
function seedWidget(node, inputName, inputData, app, widgetName) {
|
||||||
const seed = createIntWidget(node, inputName, inputData, app, true);
|
const seed = createIntWidget(node, inputName, inputData, app, true);
|
||||||
const seedControl = addValueControlWidget(node, seed.widget, "randomize");
|
const seedControl = addValueControlWidget(node, seed.widget, "randomize", undefined, widgetName);
|
||||||
|
|
||||||
seed.widget.linkedWidgets = [seedControl];
|
seed.widget.linkedWidgets = [seedControl];
|
||||||
return seed;
|
return seed;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createIntWidget(node, inputName, inputData, app, isSeedInput) {
|
function createIntWidget(node, inputName, inputData, app, isSeedInput) {
|
||||||
if (!isSeedInput && inputData[1]?.control_after_generate) {
|
const control = inputData[1]?.control_after_generate;
|
||||||
return seedWidget(node, inputName, inputData, app);
|
if (!isSeedInput && control) {
|
||||||
|
return seedWidget(node, inputName, inputData, app, typeof control === "string" ? control : undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
let widgetType = isSlider(inputData[1]["display"], app);
|
let widgetType = isSlider(inputData[1]["display"], app);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user