Improve error handling

This commit is contained in:
kijai 2023-10-10 13:01:25 +03:00
parent 3f42ff5d05
commit c78d261698
2 changed files with 117 additions and 178 deletions

View File

@ -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.

View File

@ -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, {