mirror of
https://git.datalinker.icu/kijai/ComfyUI-KJNodes.git
synced 2026-05-18 23:17:23 +08:00
Improve error handling
This commit is contained in:
parent
3f42ff5d05
commit
c78d261698
20
README.md
20
README.md
@ -1,6 +1,10 @@
|
|||||||
# KJNodes for ComfyUI
|
# KJNodes for ComfyUI
|
||||||
|
|
||||||
Various quality of life -nodes made by combining functionality of existing nodes for ComfyUI, mostly just visual stuff to improve usability.
|
Various quality of life and masking related -nodes and scripts made by combining functionality of existing nodes for ComfyUI.
|
||||||
|
|
||||||
|
# Installation
|
||||||
|
1. Clone this repo into `custom_nodes` folder.
|
||||||
|
2. Install dependencies: pip install -r requirements.txt
|
||||||
|
|
||||||
## Javascript
|
## Javascript
|
||||||
|
|
||||||
@ -16,11 +20,11 @@ Could still be buggy, especially when loading workflow with missing nodes, use w
|
|||||||
|
|
||||||
### ColorToMask
|
### ColorToMask
|
||||||
|
|
||||||
RBG color value to mask, works with batches and AnimateDiff
|
RBG color value to mask, works with batches and AnimateDiff.
|
||||||
|
|
||||||
### ConditioningMultiCombine
|
### ConditioningMultiCombine
|
||||||
|
|
||||||
Combine any number of conditions, saves space
|
Combine any number of conditions, saves space.
|
||||||
|
|
||||||
### ConditioningSetMaskAndCombine
|
### ConditioningSetMaskAndCombine
|
||||||
|
|
||||||
@ -30,6 +34,10 @@ Mask and combine two sets of conditions, saves space.
|
|||||||
|
|
||||||
Grows or shrinks (with negative values) mask, option to invert input, returns mask and inverted mask. Additionally Blurs the mask, this is a slow operation especially with big batches.
|
Grows or shrinks (with negative values) mask, option to invert input, returns mask and inverted mask. Additionally Blurs the mask, this is a slow operation especially with big batches.
|
||||||
|
|
||||||
# Installation
|
### CreateFadeMask
|
||||||
1. Clone this repo into `custom_nodes` folder.
|
|
||||||
2. Install dependencies: pip install -r requirements.txt
|
This node creates batch of single color images by interpolating between white/black levels. Useful to control mask strengths or QR code controlnet input weight when combined with MaskComposite node.
|
||||||
|
|
||||||
|
### CreateAudioMask
|
||||||
|
|
||||||
|
Work in progress, currently creates a sphere that's size is synced with audio input.
|
||||||
|
|||||||
@ -3,6 +3,26 @@ import { ComfyWidgets } from '../../../scripts/widgets.js';
|
|||||||
//based on diffus3's SetGet: https://github.com/diffus3/ComfyUI-extensions
|
//based on diffus3's SetGet: https://github.com/diffus3/ComfyUI-extensions
|
||||||
|
|
||||||
// Nodes that allow you to tunnel connections for cleaner graphs
|
// Nodes that allow you to tunnel connections for cleaner graphs
|
||||||
|
function setColorAndBgColor(type) {
|
||||||
|
const colorMap = {
|
||||||
|
"MODEL": LGraphCanvas.node_colors.blue,
|
||||||
|
"LATENT": LGraphCanvas.node_colors.purple,
|
||||||
|
"VAE": LGraphCanvas.node_colors.red,
|
||||||
|
"CONDITIONING": LGraphCanvas.node_colors.brown,
|
||||||
|
"IMAGE": LGraphCanvas.node_colors.pale_blue,
|
||||||
|
"CLIP": LGraphCanvas.node_colors.yellow,
|
||||||
|
"INT": LGraphCanvas.node_colors.green,
|
||||||
|
"MASK": LGraphCanvas.node_colors.cyan
|
||||||
|
};
|
||||||
|
|
||||||
|
const colors = colorMap[type];
|
||||||
|
if (colors) {
|
||||||
|
this.color = colors.color;
|
||||||
|
this.bgcolor = colors.bgcolor;
|
||||||
|
} else {
|
||||||
|
// Handle the default case if needed
|
||||||
|
}
|
||||||
|
}
|
||||||
app.registerExtension({
|
app.registerExtension({
|
||||||
name: "SetNode",
|
name: "SetNode",
|
||||||
registerCustomNodes() {
|
registerCustomNodes() {
|
||||||
@ -19,7 +39,6 @@ app.registerExtension({
|
|||||||
|
|
||||||
const node = this;
|
const node = this;
|
||||||
|
|
||||||
|
|
||||||
this.addWidget(
|
this.addWidget(
|
||||||
"text",
|
"text",
|
||||||
"Constant",
|
"Constant",
|
||||||
@ -38,8 +57,6 @@ app.registerExtension({
|
|||||||
this.addInput("*", "*");
|
this.addInput("*", "*");
|
||||||
this.addOutput("*", '*');
|
this.addOutput("*", '*');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
this.onConnectionsChange = function(
|
this.onConnectionsChange = function(
|
||||||
slotType, //1 = input, 2 = output
|
slotType, //1 = input, 2 = output
|
||||||
slot,
|
slot,
|
||||||
@ -58,63 +75,42 @@ app.registerExtension({
|
|||||||
if (slotType == 2 && !isChangeConnect) {
|
if (slotType == 2 && !isChangeConnect) {
|
||||||
this.outputs[slot].type = '*';
|
this.outputs[slot].type = '*';
|
||||||
this.outputs[slot].name = '*';
|
this.outputs[slot].name = '*';
|
||||||
|
|
||||||
}
|
}
|
||||||
//On Connect
|
//On Connect
|
||||||
if (link_info && node.graph && slotType == 1 && isChangeConnect) {
|
if (link_info && node.graph && slotType == 1 && isChangeConnect) {
|
||||||
|
|
||||||
const fromNode = node.graph._nodes.find((otherNode) => otherNode.id == link_info.origin_id);
|
const fromNode = node.graph._nodes.find((otherNode) => otherNode.id == link_info.origin_id);
|
||||||
const type = fromNode.outputs[link_info.origin_slot].type;
|
|
||||||
|
|
||||||
if (this.title === "Set"){
|
if (fromNode && fromNode.outputs && fromNode.outputs[link_info.origin_slot]) {
|
||||||
console.log("setting title to Set_" + type);
|
const type = fromNode.outputs[link_info.origin_slot].type;
|
||||||
this.title = "Set_" + type;
|
|
||||||
}
|
|
||||||
if (this.widgets[0].value === '*'){
|
|
||||||
console.log("setting default value to " + type);
|
|
||||||
this.widgets[0].value = type
|
|
||||||
}
|
|
||||||
|
|
||||||
this.validateName(node.graph);
|
if (this.title === "Set"){
|
||||||
this.inputs[0].type = type;
|
this.title = "Set_" + type;
|
||||||
this.inputs[0].name = type;
|
}
|
||||||
|
if (this.widgets[0].value === '*'){
|
||||||
switch (type) {
|
this.widgets[0].value = type
|
||||||
case "MODEL":
|
}
|
||||||
this.color = LGraphCanvas.node_colors.blue.color;
|
|
||||||
this.bgcolor = LGraphCanvas.node_colors.blue.bgcolor;
|
this.validateName(node.graph);
|
||||||
break;
|
this.inputs[0].type = type;
|
||||||
case "LATENT":
|
this.inputs[0].name = type;
|
||||||
this.color = LGraphCanvas.node_colors.purple.color;
|
|
||||||
this.bgcolor = LGraphCanvas.node_colors.purple.bgcolor;
|
setColorAndBgColor.call(this, type);
|
||||||
break;
|
} else {
|
||||||
case "VAE":
|
alert("Error: Set node input undefined. Most likely you're missing custom nodes");
|
||||||
this.color = LGraphCanvas.node_colors.red.color;
|
|
||||||
this.bgcolor = LGraphCanvas.node_colors.red.bgcolor;
|
|
||||||
break;
|
|
||||||
case "CONDITIONING":
|
|
||||||
this.color = LGraphCanvas.node_colors.brown.color;
|
|
||||||
this.bgcolor = LGraphCanvas.node_colors.brown.bgcolor;
|
|
||||||
break;
|
|
||||||
case "IMAGE":
|
|
||||||
this.color = LGraphCanvas.node_colors.pale_blue.color;
|
|
||||||
this.bgcolor = LGraphCanvas.node_colors.pale_blue.bgcolor;
|
|
||||||
break;
|
|
||||||
case "CLIP":
|
|
||||||
this.color = LGraphCanvas.node_colors.yellow.color;
|
|
||||||
this.bgcolor = LGraphCanvas.node_colors.yellow.bgcolor;
|
|
||||||
break;
|
|
||||||
case "INT":
|
|
||||||
this.color = LGraphCanvas.node_colors.green.color;
|
|
||||||
this.bgcolor = LGraphCanvas.node_colors.green.bgcolor;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (link_info && node.graph && slotType == 2 && isChangeConnect) {
|
if (link_info && node.graph && slotType == 2 && isChangeConnect) {
|
||||||
const fromNode = node.graph._nodes.find((otherNode) => otherNode.id == link_info.origin_id);
|
const fromNode = node.graph._nodes.find((otherNode) => otherNode.id == link_info.origin_id);
|
||||||
const type = fromNode.inputs[link_info.origin_slot].type;
|
|
||||||
|
if (fromNode && fromNode.inputs && fromNode.inputs[link_info.origin_slot]) {
|
||||||
this.outputs[0].type = type;
|
const type = fromNode.inputs[link_info.origin_slot].type;
|
||||||
this.outputs[0].name = type;
|
|
||||||
|
this.outputs[0].type = type;
|
||||||
|
this.outputs[0].name = type;
|
||||||
|
} else {
|
||||||
|
alert("Error: Get Set node output undefined. Most likely you're missing custom nodes");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -124,26 +120,22 @@ app.registerExtension({
|
|||||||
|
|
||||||
this.validateName = function(graph) {
|
this.validateName = function(graph) {
|
||||||
let widgetValue = node.widgets[0].value;
|
let widgetValue = node.widgets[0].value;
|
||||||
|
|
||||||
if (widgetValue != '') {
|
if (widgetValue !== '') {
|
||||||
let tries = 0;
|
let tries = 0;
|
||||||
let collisions = [];
|
const existingValues = new Set();
|
||||||
|
|
||||||
do {
|
graph._nodes.forEach(otherNode => {
|
||||||
collisions = graph._nodes.filter((otherNode) => {
|
if (otherNode !== this && otherNode.type === 'SetNode') {
|
||||||
if (otherNode == this) {
|
existingValues.add(otherNode.widgets[0].value);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (otherNode.type == 'SetNode' && otherNode.widgets[0].value === widgetValue) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
})
|
|
||||||
if (collisions.length > 0) {
|
|
||||||
widgetValue = node.widgets[0].value + "_" + tries;
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
while (existingValues.has(widgetValue)) {
|
||||||
|
widgetValue = node.widgets[0].value + "_" + tries;
|
||||||
tries++;
|
tries++;
|
||||||
} while (collisions.length > 0)
|
}
|
||||||
|
|
||||||
node.widgets[0].value = widgetValue;
|
node.widgets[0].value = widgetValue;
|
||||||
this.update();
|
this.update();
|
||||||
}
|
}
|
||||||
@ -165,46 +157,41 @@ app.registerExtension({
|
|||||||
|
|
||||||
|
|
||||||
this.update = function() {
|
this.update = function() {
|
||||||
if (node.graph) {
|
if (!node.graph) {
|
||||||
this.findGetters(node.graph).forEach((getter) => {
|
return;
|
||||||
|
|
||||||
getter.setType(this.inputs[0].type);
|
|
||||||
});
|
|
||||||
if (this.widgets[0].value) {
|
|
||||||
this.findGetters(node.graph, true).forEach((getter) => {
|
|
||||||
getter.setName(this.widgets[0].value)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const allGetters = node.graph._nodes.filter((otherNode) => otherNode.type == "GetNode");
|
|
||||||
allGetters.forEach((otherNode) => {
|
|
||||||
if (otherNode.setComboValues) {
|
|
||||||
otherNode.setComboValues();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getters = this.findGetters(node.graph);
|
||||||
|
getters.forEach(getter => {
|
||||||
|
getter.setType(this.inputs[0].type);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (this.widgets[0].value) {
|
||||||
|
const gettersWithPreviousName = this.findGetters(node.graph, true);
|
||||||
|
gettersWithPreviousName.forEach(getter => {
|
||||||
|
getter.setName(this.widgets[0].value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const allGetters = node.graph._nodes.filter(otherNode => otherNode.type === "GetNode");
|
||||||
|
allGetters.forEach(otherNode => {
|
||||||
|
if (otherNode.setComboValues) {
|
||||||
|
otherNode.setComboValues();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
this.findGetters = function(graph, checkForPreviousName) {
|
this.findGetters = function(graph, checkForPreviousName) {
|
||||||
const name = checkForPreviousName ? this.properties.previousName : this.widgets[0].value;
|
const name = checkForPreviousName ? this.properties.previousName : this.widgets[0].value;
|
||||||
return graph._nodes.filter((otherNode) => {
|
return graph._nodes.filter(otherNode => otherNode.type === 'GetNode' && otherNode.widgets[0].value === name && name !== '');
|
||||||
if (otherNode.type == 'GetNode' && otherNode.widgets[0].value === name && name != '') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// This node is purely frontend and does not impact the resulting prompt so should not be serialized
|
// This node is purely frontend and does not impact the resulting prompt so should not be serialized
|
||||||
this.isVirtualNode = true;
|
this.isVirtualNode = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
onRemoved() {
|
onRemoved() {
|
||||||
// console.log("onRemove");
|
|
||||||
// console.log(this);
|
|
||||||
// console.log(this.flags);
|
|
||||||
const allGetters = this.graph._nodes.filter((otherNode) => otherNode.type == "GetNode");
|
const allGetters = this.graph._nodes.filter((otherNode) => otherNode.type == "GetNode");
|
||||||
allGetters.forEach((otherNode) => {
|
allGetters.forEach((otherNode) => {
|
||||||
if (otherNode.setComboValues) {
|
if (otherNode.setComboValues) {
|
||||||
@ -214,7 +201,6 @@ app.registerExtension({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LiteGraph.registerNodeType(
|
LiteGraph.registerNodeType(
|
||||||
"SetNode",
|
"SetNode",
|
||||||
Object.assign(SetNode, {
|
Object.assign(SetNode, {
|
||||||
@ -226,7 +212,6 @@ app.registerExtension({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
app.registerExtension({
|
app.registerExtension({
|
||||||
name: "GetNode",
|
name: "GetNode",
|
||||||
registerCustomNodes() {
|
registerCustomNodes() {
|
||||||
@ -257,10 +242,7 @@ app.registerExtension({
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
this.addOutput("*", '*');
|
||||||
this.addOutput("*", '*');
|
|
||||||
|
|
||||||
|
|
||||||
this.onConnectionsChange = function(
|
this.onConnectionsChange = function(
|
||||||
slotType, //0 = output, 1 = input
|
slotType, //0 = output, 1 = input
|
||||||
slot, //self-explanatory
|
slot, //self-explanatory
|
||||||
@ -270,15 +252,13 @@ app.registerExtension({
|
|||||||
) {
|
) {
|
||||||
this.validateLinks();
|
this.validateLinks();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
this.setName = function(name) {
|
this.setName = function(name) {
|
||||||
node.widgets[0].value = name;
|
node.widgets[0].value = name;
|
||||||
node.onRename();
|
node.onRename();
|
||||||
node.serialize();
|
node.serialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
this.onRename = function() {
|
this.onRename = function() {
|
||||||
const setter = this.findSetter(node.graph);
|
const setter = this.findSetter(node.graph);
|
||||||
if (setter) {
|
if (setter) {
|
||||||
@ -286,36 +266,8 @@ app.registerExtension({
|
|||||||
|
|
||||||
this.setType(linkType);
|
this.setType(linkType);
|
||||||
this.title = "Get_" + setter.widgets[0].value;
|
this.title = "Get_" + setter.widgets[0].value;
|
||||||
switch (linkType) {
|
|
||||||
case "MODEL":
|
setColorAndBgColor.call(this, linkType);
|
||||||
this.color = LGraphCanvas.node_colors.blue.color;
|
|
||||||
this.bgcolor = LGraphCanvas.node_colors.blue.bgcolor;
|
|
||||||
break;
|
|
||||||
case "LATENT":
|
|
||||||
this.color = LGraphCanvas.node_colors.purple.color;
|
|
||||||
this.bgcolor = LGraphCanvas.node_colors.purple.bgcolor;
|
|
||||||
break;
|
|
||||||
case "VAE":
|
|
||||||
this.color = LGraphCanvas.node_colors.red.color;
|
|
||||||
this.bgcolor = LGraphCanvas.node_colors.red.bgcolor;
|
|
||||||
break;
|
|
||||||
case "CONDITIONING":
|
|
||||||
this.color = LGraphCanvas.node_colors.brown.color;
|
|
||||||
this.bgcolor = LGraphCanvas.node_colors.brown.bgcolor;
|
|
||||||
break;
|
|
||||||
case "IMAGE":
|
|
||||||
this.color = LGraphCanvas.node_colors.pale_blue.color;
|
|
||||||
this.bgcolor = LGraphCanvas.node_colors.pale_blue.bgcolor;
|
|
||||||
break;
|
|
||||||
case "CLIP":
|
|
||||||
this.color = LGraphCanvas.node_colors.yellow.color;
|
|
||||||
this.bgcolor = LGraphCanvas.node_colors.yellow.bgcolor;
|
|
||||||
break;
|
|
||||||
case "INT":
|
|
||||||
this.color = LGraphCanvas.node_colors.green.color;
|
|
||||||
this.bgcolor = LGraphCanvas.node_colors.green.bgcolor;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
this.setType('*');
|
this.setType('*');
|
||||||
@ -329,18 +281,15 @@ app.registerExtension({
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.validateLinks = function() {
|
this.validateLinks = function() {
|
||||||
//console.log("validating links");
|
if (this.outputs[0].type !== '*' && this.outputs[0].links) {
|
||||||
if (this.outputs[0].type != '*' && this.outputs[0].links) {
|
this.outputs[0].links.filter(linkId => {
|
||||||
//console.log("in");
|
|
||||||
this.outputs[0].links.forEach((linkId) => {
|
|
||||||
const link = node.graph.links[linkId];
|
const link = node.graph.links[linkId];
|
||||||
if (link && link.type != this.outputs[0].type && link.type != '*') {
|
return link && (link.type !== this.outputs[0].type && link.type !== '*');
|
||||||
//console.log("removing link");
|
}).forEach(linkId => {
|
||||||
node.graph.removeLink(linkId)
|
node.graph.removeLink(linkId);
|
||||||
}
|
});
|
||||||
})
|
}
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
this.setType = function(type) {
|
this.setType = function(type) {
|
||||||
this.outputs[0].name = type;
|
this.outputs[0].name = type;
|
||||||
@ -350,48 +299,30 @@ app.registerExtension({
|
|||||||
|
|
||||||
this.findSetter = function(graph) {
|
this.findSetter = function(graph) {
|
||||||
const name = this.widgets[0].value;
|
const name = this.widgets[0].value;
|
||||||
return graph._nodes.find((otherNode) => {
|
return graph._nodes.find(otherNode => otherNode.type === 'SetNode' && otherNode.widgets[0].value === name && name !== '');
|
||||||
if (otherNode.type == 'SetNode' && otherNode.widgets[0].value === name && name != '') {
|
};
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// This node is purely frontend and does not impact the resulting prompt so should not be serialized
|
// This node is purely frontend and does not impact the resulting prompt so should not be serialized
|
||||||
this.isVirtualNode = true;
|
this.isVirtualNode = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
getInputLink(slot) {
|
getInputLink(slot) {
|
||||||
const setter = this.findSetter(this.graph);
|
const setter = this.findSetter(this.graph);
|
||||||
|
|
||||||
if (setter) {
|
if (setter) {
|
||||||
const slot_info = setter.inputs[slot];
|
const slotInfo = setter.inputs[slot];
|
||||||
//console.log("slot info");
|
const link = this.graph.links[slotInfo.link];
|
||||||
//console.log(slot_info);
|
return link;
|
||||||
//console.log(this.graph.links);
|
|
||||||
const link = this.graph.links[ slot_info.link ];
|
|
||||||
//console.log("link:");
|
|
||||||
//console.log(link);
|
|
||||||
return link;
|
|
||||||
} else {
|
} else {
|
||||||
//console.log(this.widgets[0]);
|
const errorMessage = "No SetNode found for " + this.widgets[0].value + "(" + this.type + ")";
|
||||||
//console.log(this.widgets[0].value);
|
alert(errorMessage);
|
||||||
alert("No SetNode found for " + this.widgets[0].value + "(" + this.type + ")");
|
throw new Error(errorMessage);
|
||||||
throw new Error("No SetNode found for " + this.widgets[0].value + "(" + this.type + ")");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
onAdded(graph) {
|
onAdded(graph) {
|
||||||
//this.setComboValues();
|
|
||||||
//this.validateName(graph);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LiteGraph.registerNodeType(
|
LiteGraph.registerNodeType(
|
||||||
"GetNode",
|
"GetNode",
|
||||||
Object.assign(GetNode, {
|
Object.assign(GetNode, {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user