Skip to content

Commit

Permalink
0.59
Browse files Browse the repository at this point in the history
  • Loading branch information
justUmen committed Nov 22, 2024
1 parent 3d8d945 commit 0a968c1
Show file tree
Hide file tree
Showing 12 changed files with 266 additions and 166 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# 🔗 Comfyui : Bjornulf_custom_nodes v0.58 🔗
# 🔗 Comfyui : Bjornulf_custom_nodes v0.59 🔗

A list of 68 custom nodes for Comfyui : Display, manipulate, and edit text, images, videos, loras and more.
You can manage looping operations, generate randomized content, trigger logical conditions, pause and manually control your workflows and even work with external AI tools, like Ollama or Text To Speech.
Expand Down Expand Up @@ -284,6 +284,7 @@ cd /where/you/installed/ComfyUI && python main.py
- **0.56**: ❗Breaking changes : ollama node simplified, no ollama_ip.txt needed, waiting for collection ollama nodes to be ready.
- **0.57**: ❗❗Huge changes, new Ollama node "Ollama Chat" with real functionalities. 5 Ollama nodes total. (Model selector + Job selector + Persona selector + Ollama vision + Ollama Talk) Ollama talk use context and can use context file. Add number of lines / current counter + next to sequential nodes. Add new node STT. (+ faster_whisper dep) better management of empty loras/checkpoints on selectors. (list preset) Add "default_for_language" for TTS node, taking the default voice for a language (ex: fr/default.wav) Otherwise take the first wav with the selected language.
- **0.58**: small fix in model selector default value. (Set to None by default)
- **0.59**: A lot of Javascript fixing to avoid resizing and better properties mangement / recoveries

# 📝 Nodes descriptions

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[project]
name = "bjornulf_custom_nodes"
description = "61 ComfyUI nodes : Display, manipulate, and edit text, images, videos, loras and more. Manage looping operations, generate randomized content, use logical conditions and work with external AI tools, like Ollama or Text To Speech."
version = "0.58"
version = "0.59"
license = {file = "LICENSE"}

[project.urls]
Expand Down
2 changes: 2 additions & 0 deletions web/js/combine_images.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ app.registerExtension({
async nodeCreated(node) {
if (node.comfyClass === "Bjornulf_CombineImages") {
const updateInputs = () => {
const initialWidth = node.size[0];
const numInputsWidget = node.widgets.find(w => w.name === "number_of_images");
if (!numInputsWidget) return;

Expand Down Expand Up @@ -33,6 +34,7 @@ app.registerExtension({
}

node.setSize(node.computeSize());
node.size[0] = initialWidth; // Keep width fixed
};

// Move number_of_images to the top initially
Expand Down
2 changes: 2 additions & 0 deletions web/js/combine_texts.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ app.registerExtension({
async nodeCreated(node) {
if (node.comfyClass === "Bjornulf_CombineTexts") {
const updateInputs = () => {
const initialWidth = node.size[0];
const numInputsWidget = node.widgets.find(w => w.name === "number_of_inputs");
if (!numInputsWidget) return;

Expand Down Expand Up @@ -33,6 +34,7 @@ app.registerExtension({
}

node.setSize(node.computeSize());
node.size[0] = initialWidth; // Keep width fixed
};

// Move number_of_inputs to the top initially
Expand Down
2 changes: 2 additions & 0 deletions web/js/loop_images.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ app.registerExtension({
async nodeCreated(node) {
if (node.comfyClass === "Bjornulf_LoopImages") {
const updateInputs = () => {
const initialWidth = node.size[0];
const numInputsWidget = node.widgets.find(w => w.name === "number_of_images");
if (!numInputsWidget) return;

Expand Down Expand Up @@ -33,6 +34,7 @@ app.registerExtension({
}

node.setSize(node.computeSize());
node.size[0] = initialWidth; // Keep width fixed
};

// Move number_of_images to the top initially
Expand Down
147 changes: 97 additions & 50 deletions web/js/loop_lora_selector.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,63 +4,95 @@ app.registerExtension({
name: "Bjornulf.LoopLoraSelector",
async nodeCreated(node) {
if (node.comfyClass === "Bjornulf_LoopLoraSelector") {
node.properties = node.properties || {};

const updateLoraInputs = () => {
const initialWidth = node.size[0];
const numLorasWidget = node.widgets.find(w => w.name === "number_of_loras");
if (!numLorasWidget) return;

const numLoras = numLorasWidget.value;
const loraList = node.widgets.find(w => w.name === "lora_1").options.values;
const loraList = node.widgets.find(w => w.name === "lora_1")?.options?.values || [];

// Remove excess lora widgets
node.widgets = node.widgets.filter(w => !w.name.startsWith("lora_") || parseInt(w.name.split("_")[1]) <= numLoras);

// Remove excess lora widgets and their corresponding strength widgets
// Store current widget values in properties
node.widgets.forEach(w => {
if (w.name.startsWith("lora_") ||
w.name.startsWith("strength_model_") ||
w.name.startsWith("strength_clip_")) {
node.properties[w.name] = w.value;
}
});

// Remove all lora-related widgets
node.widgets = node.widgets.filter(w =>
!w.name.startsWith("lora_") &&
!w.name.startsWith("strength_model_") &&
!w.name.startsWith("strength_clip_") ||
parseInt(w.name.split("_").pop()) <= numLoras
!w.name.startsWith("strength_clip_")
);

// Add new lora widgets and their corresponding strength widgets if needed
// Add widgets only for the specified number of loras
for (let i = 1; i <= numLoras; i++) {
const loraWidgetName = `lora_${i}`;
const strengthModelWidgetName = `strength_model_${i}`;
const strengthClipWidgetName = `strength_clip_${i}`;

if (!node.widgets.find(w => w.name === loraWidgetName)) {
const defaultIndex = Math.min(i - 1, loraList.length - 1);
node.addWidget("combo", loraWidgetName, loraList[defaultIndex], () => {}, {
// Add lora widget
const savedLoraValue = node.properties[loraWidgetName];
const loraWidget = node.addWidget("combo", loraWidgetName,
savedLoraValue !== undefined ? savedLoraValue : loraList[0],
(value) => {
node.properties[loraWidgetName] = value;
}, {
values: loraList
});
}
}
);

if (!node.widgets.find(w => w.name === strengthModelWidgetName)) {
node.addWidget("number", strengthModelWidgetName, 1.0, () => {}, {
// Add strength model widget
const savedModelValue = node.properties[strengthModelWidgetName];
const strengthModelWidget = node.addWidget("number", strengthModelWidgetName,
savedModelValue !== undefined ? savedModelValue : 1.0,
(value) => {
node.properties[strengthModelWidgetName] = value;
}, {
min: -100.0, max: 100.0, step: 0.01
});
}
}
);

if (!node.widgets.find(w => w.name === strengthClipWidgetName)) {
node.addWidget("number", strengthClipWidgetName, 1.0, () => {}, {
// Add strength clip widget
const savedClipValue = node.properties[strengthClipWidgetName];
const strengthClipWidget = node.addWidget("number", strengthClipWidgetName,
savedClipValue !== undefined ? savedClipValue : 1.0,
(value) => {
node.properties[strengthClipWidgetName] = value;
}, {
min: -100.0, max: 100.0, step: 0.01
});
}
}
);
}

// Reorder widgets
// Reorder widgets: number_of_loras first, then grouped lora widgets
const orderedWidgets = [node.widgets.find(w => w.name === "number_of_loras")];
for (let i = 1; i <= numLoras; i++) {
orderedWidgets.push(
node.widgets.find(w => w.name === `lora_${i}`),
node.widgets.find(w => w.name === `strength_model_${i}`),
node.widgets.find(w => w.name === `strength_clip_${i}`)
const loraWidgets = node.widgets.filter(w =>
w.name === `lora_${i}` ||
w.name === `strength_model_${i}` ||
w.name === `strength_clip_${i}`
);
orderedWidgets.push(...loraWidgets);
}

// Add any remaining widgets
orderedWidgets.push(...node.widgets.filter(w => !orderedWidgets.includes(w)));
node.widgets = orderedWidgets.filter(w => w !== undefined);
node.widgets = orderedWidgets;

node.setSize(node.computeSize());
node.size[0] = initialWidth; // Keep width fixed
};

// Set up number_of_loras widget
// Set up number_of_loras widget callback
const numLorasWidget = node.widgets.find(w => w.name === "number_of_loras");
if (numLorasWidget) {
numLorasWidget.callback = () => {
Expand All @@ -76,32 +108,47 @@ app.registerExtension({
originalOnConfigure.call(this, info);
}

// Restore lora widgets and strength widgets based on saved properties
const savedProperties = info.properties;
if (savedProperties) {
Object.keys(savedProperties).forEach(key => {
if (key.startsWith("lora_") || key.startsWith("strength_model_") || key.startsWith("strength_clip_")) {
const widgetName = key;
const widgetValue = savedProperties[key];
const existingWidget = node.widgets.find(w => w.name === widgetName);
if (existingWidget) {
existingWidget.value = widgetValue;
} else {
if (key.startsWith("lora_")) {
node.addWidget("combo", widgetName, widgetValue, () => {}, {
values: node.widgets.find(w => w.name === "lora_1").options.values
});
} else {
node.addWidget("number", widgetName, widgetValue, () => {}, {
min: -100.0, max: 100.0, step: 0.01
});
}
}
}
});
// if (info.properties) {
// // Restore properties
// Object.assign(this.properties, info.properties);
// }
// const savedProperties = info.properties;
// if (savedProperties) {
// Object.keys(savedProperties).forEach(key => {
// if (key.startsWith("lora_") || key.startsWith("strength_model_") || key.startsWith("strength_clip_")) {
// const widgetName = key;
// const widgetValue = savedProperties[key];
// const existingWidget = node.widgets.find(w =>
// w.name === widgetName
// );
// if (existingWidget) {
// existingWidget.value = widgetValue;
// } else {
// const baseWidget = node.widgets.find(w =>
// w.name === "lora_1" ||
// w.name === "strength_model_1" ||
// w.name === "strength_clip_1"
// );
// if (baseWidget) {
// node.addWidget("combo", widgetName, widgetValue, () => {}, {
// values: baseWidget.options.values
// });
// }
// }
// }
// });
// }
// Save properties during serialization
const originalOnSerialize = node.onSerialize;
node.onSerialize = function(info) {
if (originalOnSerialize) {
originalOnSerialize.call(this, info);
}

// Update lora inputs after restoring saved state
info.properties = { ...this.properties };
};


// Update the widgets based on the current number_of_loras value
updateLoraInputs();
};

Expand Down
2 changes: 2 additions & 0 deletions web/js/loop_model_clip_vae.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ app.registerExtension({
async nodeCreated(node) {
if (node.comfyClass === "Bjornulf_LoopModelClipVae") {
const updateInputs = () => {
const initialWidth = node.size[0];
const numInputsWidget = node.widgets.find(w => w.name === "number_of_inputs");
if (!numInputsWidget) return;

Expand Down Expand Up @@ -46,6 +47,7 @@ app.registerExtension({
}

node.setSize(node.computeSize());
node.size[0] = initialWidth; // Keep width fixed
};

// Move number_of_inputs to the top initially
Expand Down
Loading

0 comments on commit 0a968c1

Please sign in to comment.