mirror of
https://github.com/justUmen/Bjornulf_custom_nodes.git
synced 2026-03-21 20:52:11 -03:00
0.17
This commit is contained in:
11
README.md
11
README.md
@@ -1,4 +1,4 @@
|
||||
# 🔗 Comfyui : Bjornulf_custom_nodes v0.16 🔗
|
||||
# 🔗 Comfyui : Bjornulf_custom_nodes v0.17 🔗
|
||||
|
||||
# Dependencies
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
- **v0.14**: Add a new node: Cut image from a mask
|
||||
- **v0.15**: Add two new nodes: TTS - Text to Speech and Character Description Generator
|
||||
- **v0.16**: Big changes on Character Description Generator
|
||||
- **v0.17**: New loop node, combine by lines.
|
||||
|
||||
# 📝 Nodes descriptions
|
||||
|
||||
@@ -264,3 +265,11 @@ Generate a character description based on a json file in the folder `characters`
|
||||
Make your own json file with your own characters, and use this node to generate a description.
|
||||
❗ For now it's very basic node, a lot of things are going to be added and changed !!!
|
||||
Some details are unusable for some checkpoints, very much a work in progress, the json structure isn't set in stone either.
|
||||
|
||||
### 33 - ♻ Loop (All Lines from input 🔗 combine by lines)
|
||||
|
||||

|
||||
|
||||
**Description:**
|
||||
Sometimes you want to loop over several inputs but you also want to separate different lines of your output.
|
||||
So with this node, you can have the number of inputs and outputs you want. See example for usage.
|
||||
@@ -37,6 +37,7 @@ from .load_image_alpha import LoadImageWithTransparency
|
||||
from .image_mask_cutter import ImageMaskCutter
|
||||
from .character_description import CharacterDescriptionGenerator
|
||||
from .text_to_speech import TextToSpeech
|
||||
from .loop_combine_texts_by_lines import CombineTextsByLines
|
||||
# from .check_black_image import CheckBlackImage
|
||||
# from .clear_vram import ClearVRAM
|
||||
|
||||
@@ -45,6 +46,7 @@ from .text_to_speech import TextToSpeech
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
# "Bjornulf_CustomStringType": CustomStringType,
|
||||
"Bjornulf_ollamaLoader": ollamaLoader,
|
||||
"Bjornulf_CombineTextsByLines": CombineTextsByLines,
|
||||
"Bjornulf_TextToSpeech": TextToSpeech,
|
||||
"Bjornulf_CharacterDescriptionGenerator": CharacterDescriptionGenerator,
|
||||
"Bjornulf_ImageMaskCutter": ImageMaskCutter,
|
||||
@@ -90,6 +92,7 @@ NODE_CLASS_MAPPINGS = {
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
# "Bjornulf_CustomStringType": "!!! CUSTOM STRING TYPE !!!",
|
||||
"Bjornulf_ollamaLoader": "🦙 Ollama (Description)",
|
||||
"Bjornulf_CombineTextsByLines": "♻ Loop (All Lines from input 🔗 combine by lines)",
|
||||
"Bjornulf_TextToSpeech": "🔊 TTS - Text to Speech",
|
||||
"Bjornulf_CharacterDescriptionGenerator": "🧑📝 Character Description Generator",
|
||||
"Bjornulf_ImageMaskCutter": "🖼✂ Cut Image with Mask",
|
||||
|
||||
49
loop_combine_texts_by_lines.py
Normal file
49
loop_combine_texts_by_lines.py
Normal file
@@ -0,0 +1,49 @@
|
||||
class CombineTextsByLines:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"number_of_inputs": ("INT", {"default": 2, "min": 1, "max": 10, "step": 1}),
|
||||
"number_of_lines": ("INT", {"default": 3, "min": 1, "max": 20, "step": 1}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = tuple(["STRING"] * 20) # Maximum 20 lines
|
||||
RETURN_NAMES = tuple([f"line_{i+1}" for i in range(20)])
|
||||
FUNCTION = "extract_lines"
|
||||
OUTPUT_NODE = True
|
||||
CATEGORY = "text"
|
||||
OUTPUT_IS_LIST = tuple([True] * 20) # Indicate that all outputs are lists
|
||||
|
||||
def extract_lines(self, number_of_inputs, number_of_lines, **kwargs):
|
||||
grouped_lines = [[] for _ in range(number_of_lines)]
|
||||
|
||||
for i in range(1, number_of_inputs + 1):
|
||||
text_key = f"text_{i}"
|
||||
if text_key in kwargs and kwargs[text_key]:
|
||||
lines = kwargs[text_key].split('\n')
|
||||
lines = [line.strip() for line in lines if line.strip()]
|
||||
for j, line in enumerate(lines[:number_of_lines]):
|
||||
grouped_lines[j].append(line)
|
||||
|
||||
outputs = []
|
||||
for group in grouped_lines:
|
||||
# Instead of joining the lines, keep them as a list
|
||||
outputs.append(group)
|
||||
|
||||
# Pad the output to always return 20 items
|
||||
outputs.extend([[] for _ in range(20 - len(outputs))])
|
||||
|
||||
return tuple(outputs)
|
||||
|
||||
@classmethod
|
||||
def IS_CHANGED(cls, number_of_inputs, number_of_lines, ** kwargs):
|
||||
return float("NaN") # This forces the node to always update
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(cls, number_of_inputs, number_of_lines, **kwargs):
|
||||
if number_of_lines < 1 or number_of_lines > 20:
|
||||
return "Number of lines must be between 1 and 20"
|
||||
if number_of_inputs < 1 or number_of_inputs > 10:
|
||||
return "Number of inputs must be between 1 and 10"
|
||||
return True
|
||||
@@ -1,7 +1,7 @@
|
||||
[project]
|
||||
name = "bjornulf_custom_nodes"
|
||||
description = "Nodes: Ollama, Text to Speech, Save image for Bjornulf LobeChat, Text with random Seed, Random line from input, Combine images (Background+Overlay alpha), Image to grayscale (black & white), Remove image Transparency (alpha), Resize Image, ..."
|
||||
version = "0.16"
|
||||
version = "0.17"
|
||||
license = {file = "LICENSE"}
|
||||
|
||||
[project.urls]
|
||||
|
||||
BIN
screenshots/loop_combined.png
Normal file
BIN
screenshots/loop_combined.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 453 KiB |
@@ -40,7 +40,7 @@ class TextToSpeech:
|
||||
|
||||
RETURN_TYPES = ("AUDIO",)
|
||||
FUNCTION = "generate_audio"
|
||||
CATEGORY = "audio"
|
||||
CATEGORY = "Bjornulf"
|
||||
|
||||
def generate_audio(self, text, language, speaker_wav):
|
||||
# Check if a valid speaker_wav was selected
|
||||
|
||||
72
web/js/loop_combine_texts_by_lines.js
Normal file
72
web/js/loop_combine_texts_by_lines.js
Normal file
@@ -0,0 +1,72 @@
|
||||
import { app } from "../../../scripts/app.js";
|
||||
|
||||
app.registerExtension({
|
||||
name: "Bjornulf.CombineTextsByLines",
|
||||
async nodeCreated(node) {
|
||||
if (node.comfyClass === "Bjornulf_CombineTextsByLines") {
|
||||
const updateInputsAndOutputs = () => {
|
||||
const numInputsWidget = node.widgets.find(w => w.name === "number_of_inputs");
|
||||
const numLinesWidget = node.widgets.find(w => w.name === "number_of_lines");
|
||||
if (!numInputsWidget || !numLinesWidget) return;
|
||||
|
||||
const numInputs = numInputsWidget.value;
|
||||
const numLines = numLinesWidget.value;
|
||||
|
||||
// Update inputs
|
||||
if (!node.inputs) {
|
||||
node.inputs = [];
|
||||
}
|
||||
|
||||
// Remove excess inputs
|
||||
node.inputs = node.inputs.filter(input => !input.name.startsWith('text_') || parseInt(input.name.split('_')[1]) <= numInputs);
|
||||
|
||||
// Add new inputs if needed
|
||||
for (let i = node.inputs.length; i < numInputs; i++) {
|
||||
const inputName = `text_${i + 1}`;
|
||||
if (!node.inputs.find(input => input.name === inputName)) {
|
||||
node.addInput(inputName, "STRING");
|
||||
}
|
||||
}
|
||||
|
||||
// Update outputs
|
||||
if (!node.outputs) {
|
||||
node.outputs = [];
|
||||
}
|
||||
|
||||
// Remove excess outputs
|
||||
while (node.outputs.length > numLines) {
|
||||
node.removeOutput(node.outputs.length - 1);
|
||||
}
|
||||
|
||||
// Add new outputs if needed
|
||||
while (node.outputs.length < numLines) {
|
||||
node.addOutput(`Line ${node.outputs.length + 1}`, "STRING", { array: true });
|
||||
}
|
||||
|
||||
// Update output labels and types
|
||||
node.outputs.forEach((output, index) => {
|
||||
output.name = `line_${index + 1}`;
|
||||
output.label = `Line ${index + 1}`;
|
||||
output.type = "STRING";
|
||||
output.array = true;
|
||||
});
|
||||
|
||||
node.setSize(node.computeSize());
|
||||
};
|
||||
|
||||
// Move control widgets to the top and remove any text area widgets
|
||||
node.widgets = node.widgets.filter(w => w.name === "number_of_inputs" || w.name === "number_of_lines");
|
||||
|
||||
// Set up callbacks
|
||||
node.widgets.forEach(w => {
|
||||
w.callback = () => {
|
||||
updateInputsAndOutputs();
|
||||
app.graph.setDirtyCanvas(true);
|
||||
};
|
||||
});
|
||||
|
||||
// Initial update
|
||||
setTimeout(updateInputsAndOutputs, 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user