Remove seed parameter and add new utility nodes
Removed the seed parameter from tag injection methods for cleaner function signatures. Added new utility nodes: RandomFloat, RandomInt, SaveTextFile. Adjusted category and return types in existing node classes accordingly.
This commit is contained in:
@@ -26,6 +26,9 @@ from custom_nodes.comfyui_gr85.nodes.prompt.wildcard.random_title_character impo
|
||||
from custom_nodes.comfyui_gr85.nodes.prompt.wildcard.random_wildcard_tag_picker import RandomWildcardTagPicker
|
||||
from custom_nodes.comfyui_gr85.nodes.utils.flux_model_merge_parameters import FluxModelMergeParameters
|
||||
from custom_nodes.comfyui_gr85.nodes.utils.next_seed import NextSeed
|
||||
from custom_nodes.comfyui_gr85.nodes.utils.random_float import RandomFloat
|
||||
from custom_nodes.comfyui_gr85.nodes.utils.random_int import RandomInt
|
||||
from custom_nodes.comfyui_gr85.nodes.utils.save_text_file import SaveTextFile
|
||||
from custom_nodes.comfyui_gr85.nodes.utils.str_safe import StrSafe
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
@@ -57,6 +60,9 @@ NODE_CLASS_MAPPINGS = {
|
||||
"GR85_UpdateT5Blocks": UpdateT5Blocks,
|
||||
"GR85_GenerateDefaultClipValues": GenerateDefaultCLIPValues,
|
||||
"GR85_FluxAttentionSeeker2": FluxAttentionSeeker2,
|
||||
"GR85_RandomFloat": RandomFloat,
|
||||
"GR85_RandomInt": RandomInt,
|
||||
"GR85_SaveTextFile": SaveTextFile,
|
||||
|
||||
"GR85_FluxModelMergeParameters": FluxModelMergeParameters,
|
||||
"GR85_NextSeed": NextSeed,
|
||||
@@ -95,6 +101,9 @@ NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"GR85_UpdateT5Blocks": "Update T5 Blocks",
|
||||
"GR85_GenerateDefaultClipValues": "Generate Default CLIP Values",
|
||||
"GR85_FluxAttentionSeeker2": "Flux Attention Seeker 2",
|
||||
"GR85_RandomFloat": "Random Float",
|
||||
"GR85_RandomInt": "Random Int",
|
||||
"GR85_SaveTextFile": "Save Text File",
|
||||
|
||||
"GR85_FluxModelMergeParameters": "Flux Model Merge Parameters",
|
||||
"GR85_NextSeed": "Next Seed",
|
||||
|
||||
@@ -40,7 +40,7 @@ class IntegerSequenceModifier:
|
||||
RETURN_NAMES = ("comma_separated_list",)
|
||||
|
||||
FUNCTION = "modify_sequence"
|
||||
CATEGORY = "Custom/ComfyUI"
|
||||
CATEGORY = "GR85/Utils"
|
||||
|
||||
def modify_sequence(self, starting_int: int, amount_of_ints: int, index: int) -> tuple:
|
||||
"""
|
||||
|
||||
@@ -9,7 +9,6 @@ class TagInjector:
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"seed": ("INT", {"forceInput": True, "default": 0}),
|
||||
"template": ("STRING", {"multiline": True, "dynamicPrompts": True,
|
||||
"default": "__elements__"}),
|
||||
},
|
||||
@@ -28,7 +27,7 @@ class TagInjector:
|
||||
FUNCTION = "inject_tag"
|
||||
CATEGORY = "GR85/Prompt"
|
||||
|
||||
def inject_tag(self, seed, template, tag_1=None, tag_2=None, tag_3=None,
|
||||
def inject_tag(self, template, tag_1=None, tag_2=None, tag_3=None,
|
||||
tag_name_1="elements", tag_name_2="stuff", tag_name_3="things"):
|
||||
"""
|
||||
Inject tags into the template based on the given tag names and values.
|
||||
|
||||
@@ -9,7 +9,6 @@ class TagInjectorLarge:
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"seed": ("INT", {"forceInput": True, "default": 0}),
|
||||
"template": ("STRING", {"multiline": True, "dynamicPrompts": True,
|
||||
"default": "In a __location__ under a __weather__ sky, a __personality__ person shows __emotion__ while wearing __style__. The __time__ is perfect for a __action__ amidst __mood__."}),
|
||||
},
|
||||
@@ -42,7 +41,7 @@ class TagInjectorLarge:
|
||||
FUNCTION = "inject_tag"
|
||||
CATEGORY = "GR85/Prompt"
|
||||
|
||||
def inject_tag(self, seed, template, tag_1=None, tag_2=None, tag_3=None, tag_4=None, tag_5=None,
|
||||
def inject_tag(self, template, tag_1=None, tag_2=None, tag_3=None, tag_4=None, tag_5=None,
|
||||
tag_6=None, tag_7=None, tag_8=None, tag_9=None, tag_10=None,
|
||||
tag_name_1="location", tag_name_2="color", tag_name_3="object", tag_name_4="emotion",
|
||||
tag_name_5="weather", tag_name_6="personality", tag_name_7="time", tag_name_8="action",
|
||||
|
||||
@@ -78,6 +78,7 @@ class FluxModelMergeParameters:
|
||||
# Defines the types of values returned by the node
|
||||
RETURN_TYPES = (
|
||||
"STRING", # Comma-separated values
|
||||
"FLOAT",
|
||||
*IMAGE_INPUTS,
|
||||
*DOUBLE_BLOCKS,
|
||||
*SINGLE_BLOCKS,
|
||||
@@ -93,6 +94,7 @@ class FluxModelMergeParameters:
|
||||
# Combines all return names into a single tuple
|
||||
RETURN_NAMES = (
|
||||
"comma_separated_values",
|
||||
"average_value",
|
||||
*IMAGE_INPUT_NAMES,
|
||||
*DOUBLE_BLOCK_NAMES,
|
||||
*SINGLE_BLOCK_NAMES,
|
||||
@@ -213,5 +215,7 @@ class FluxModelMergeParameters:
|
||||
# Create a comma-separated string of all values for reference
|
||||
comma_separated_values = ", ".join(map(str, value_list))
|
||||
|
||||
average_value = sum(value_list) / len(value_list)
|
||||
|
||||
# Return the comma-separated string and unpack the list of values
|
||||
return (comma_separated_values, *value_list)
|
||||
return (comma_separated_values, average_value, *value_list)
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
import random
|
||||
|
||||
class RandomFloat:
|
||||
"""
|
||||
A ComfyUI node class that generates a random float based on given inputs.
|
||||
|
||||
Attributes:
|
||||
INPUT_TYPES (dict): Defines the required and optional input types for the node.
|
||||
RETURN_TYPES (tuple): Specifies the types of values returned by the node.
|
||||
RETURN_NAMES (tuple): Specifies the names of the returned values for better identification.
|
||||
FUNCTION (str): The function name used for processing parameters.
|
||||
CATEGORY (str): The category under which this node is classified.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
return {
|
||||
"required": {
|
||||
"seed": ("INT", {"default": 0, "min": 0, "display": "number"}),
|
||||
"min_value": ("FLOAT", {"default": 0.0, "min": -1e-10, "max": 1e10, "step": 0.0001, "display": "number"}),
|
||||
"max_value": ("FLOAT", {"default": 1.0, "min": -1e-10, "max": 1e10, "step": 0.0001, "display": "number"}),
|
||||
"decimal_places": ("INT", {"default": 10, "min": 0, "display": "number"}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("FLOAT",)
|
||||
RETURN_NAMES = ("random_float",)
|
||||
|
||||
FUNCTION = "generate_random_float"
|
||||
CATEGORY = "GR85/Utils"
|
||||
|
||||
def generate_random_float(self, seed: int, min_value: float, max_value: float, decimal_places: int) -> tuple:
|
||||
"""
|
||||
Generates a random float based on the given seed, min, max, and decimal places.
|
||||
|
||||
Args:
|
||||
seed (int): The seed value for random number generation.
|
||||
min_value (float): The minimum value of the generated float.
|
||||
max_value (float): The maximum value of the generated float.
|
||||
decimal_places (int): The number of decimal places for the generated float.
|
||||
|
||||
Returns:
|
||||
tuple: A tuple containing the generated random float.
|
||||
"""
|
||||
random.seed(seed)
|
||||
random_float = round(random.uniform(min_value, max_value), decimal_places)
|
||||
return (random_float,)
|
||||
@@ -0,0 +1,45 @@
|
||||
import random
|
||||
|
||||
class RandomInt:
|
||||
"""
|
||||
A ComfyUI node class that generates a random integer based on given inputs.
|
||||
|
||||
Attributes:
|
||||
INPUT_TYPES (dict): Defines the required and optional input types for the node.
|
||||
RETURN_TYPES (tuple): Specifies the types of values returned by the node.
|
||||
RETURN_NAMES (tuple): Specifies the names of the returned values for better identification.
|
||||
FUNCTION (str): The function name used for processing parameters.
|
||||
CATEGORY (str): The category under which this node is classified.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
return {
|
||||
"required": {
|
||||
"seed": ("INT", {"default": 0, "min": 0, "display": "number"}),
|
||||
"min_value": ("INT", {"default": 0, "min": -1e10, "max": 1e10, "display": "number"}),
|
||||
"max_value": ("INT", {"default": 100, "min": -1e10, "max": 1e10, "display": "number"}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("INT",)
|
||||
RETURN_NAMES = ("random_int",)
|
||||
|
||||
FUNCTION = "generate_random_int"
|
||||
CATEGORY = "GR85/Utils"
|
||||
|
||||
def generate_random_int(self, seed: int, min_value: int, max_value: int) -> tuple:
|
||||
"""
|
||||
Generates a random integer based on the given seed, min, and max values.
|
||||
|
||||
Args:
|
||||
seed (int): The seed value for random number generation.
|
||||
min_value (int): The minimum value of the generated integer.
|
||||
max_value (int): The maximum value of the generated integer.
|
||||
|
||||
Returns:
|
||||
tuple: A tuple containing the generated random integer.
|
||||
"""
|
||||
random.seed(seed)
|
||||
random_int = random.randint(min_value, max_value)
|
||||
return (random_int,)
|
||||
@@ -0,0 +1,101 @@
|
||||
import os
|
||||
import re
|
||||
|
||||
class SaveTextFile:
|
||||
"""
|
||||
A ComfyUI node class that saves text to a file based on given inputs.
|
||||
|
||||
Attributes:
|
||||
INPUT_TYPES (dict): Defines the required and optional input types for the node.
|
||||
RETURN_TYPES (tuple): Specifies the types of values returned by the node.
|
||||
RETURN_NAMES (tuple): Specifies the names of the returned values for better identification.
|
||||
FUNCTION (str): The function name used for processing parameters.
|
||||
CATEGORY (str): The category under which this node is classified.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls) -> dict:
|
||||
return {
|
||||
"required": {
|
||||
"text": ("STRING", {"forceInput": True, "multiline": True}), # The text content to be saved.
|
||||
"path": ("STRING", {"default": './ComfyUI/output/', "multiline": True}), # Directory path where the file will be saved.
|
||||
"filename_prefix": ("STRING", {"default": "ComfyUI"}), # Prefix for the filename.
|
||||
"filename_delimiter": ("STRING", {"default": "_"}), # Delimiter between prefix and number.
|
||||
"filename_number_padding": ("INT", {"default": 4, "min": 0, "max": 9, "step": 1}), # Number of padding zeros for the filename.
|
||||
},
|
||||
"optional": {
|
||||
"file_extension": ("STRING", {"default": ".txt"}), # File extension for the saved file.
|
||||
"encoding": ("STRING", {"default": "utf-8"}) # Encoding to use when writing the file.
|
||||
}
|
||||
}
|
||||
|
||||
OUTPUT_NODE = True
|
||||
RETURN_TYPES = ()
|
||||
FUNCTION = "save_text_file"
|
||||
CATEGORY = "GR85/Utils"
|
||||
|
||||
def save_text_file(self, text: str, path: str, filename_prefix: str = 'ComfyUI', filename_delimiter: str = '_', filename_number_padding: int = 4, file_extension: str = '.txt', encoding: str = 'utf-8'):
|
||||
# Ensure the directory exists, create if it does not exist
|
||||
if not os.path.exists(path):
|
||||
print(f"The path `{path}` doesn't exist! Creating it...")
|
||||
try:
|
||||
os.makedirs(path, exist_ok=True)
|
||||
except OSError as e:
|
||||
# If directory creation fails, print an error and return
|
||||
print(f"The path `{path}` could not be created! Is there write access?\n{e}")
|
||||
return
|
||||
|
||||
# If the text is empty, print an error and return
|
||||
if text.strip() == '':
|
||||
print(f"There is no text specified to save! Text is empty.")
|
||||
return
|
||||
|
||||
delimiter = filename_delimiter
|
||||
number_padding = int(filename_number_padding)
|
||||
# Generate the filename using the specified parameters
|
||||
filename = self.generate_filename(path, filename_prefix, delimiter, number_padding, file_extension)
|
||||
file_path = os.path.join(path, filename)
|
||||
# Write the text content to the file
|
||||
self.write_text_file(file_path, text, encoding)
|
||||
return (text, {"ui": {"string": text}})
|
||||
|
||||
def generate_filename(self, path: str, prefix: str, delimiter: str, number_padding: int, extension: str) -> str:
|
||||
# Generate a filename based on the given parameters
|
||||
if number_padding == 0:
|
||||
# If number_padding is 0, don't use a numerical suffix
|
||||
filename = f"{prefix}{extension}"
|
||||
else:
|
||||
# Create a regex pattern to match existing files with the specified prefix and delimiter
|
||||
pattern = f"{re.escape(prefix)}{re.escape(delimiter)}(\d{{{number_padding}}})"
|
||||
# Find all existing files that match the pattern and extract their counters
|
||||
existing_counters = [
|
||||
int(re.search(pattern, filename).group(1))
|
||||
for filename in os.listdir(path)
|
||||
if re.match(pattern, filename)
|
||||
]
|
||||
# Sort counters in descending order to find the highest value
|
||||
existing_counters.sort(reverse=True)
|
||||
if existing_counters:
|
||||
# Set the next counter value to the highest existing value plus one
|
||||
counter = existing_counters[0] + 1
|
||||
else:
|
||||
# If no existing files, start with counter 1
|
||||
counter = 1
|
||||
# Format the filename with the prefix, delimiter, counter, and extension
|
||||
filename = f"{prefix}{delimiter}{counter:0{number_padding}}{extension}"
|
||||
# Ensure the generated filename does not already exist
|
||||
while os.path.exists(os.path.join(path, filename)):
|
||||
counter += 1
|
||||
filename = f"{prefix}{delimiter}{counter:0{number_padding}}{extension}"
|
||||
return filename
|
||||
|
||||
def write_text_file(self, file: str, content: str, encoding: str):
|
||||
# Write the content to the specified file with the given encoding
|
||||
try:
|
||||
with open(file, 'w', encoding=encoding, newline='\n') as f:
|
||||
f.write(content)
|
||||
except OSError:
|
||||
# Print an error message if the file could not be saved
|
||||
print(f"Unable to save file `{file}`")
|
||||
|
||||
# Let me know if you need to customize or extend this node further!
|
||||
Reference in New Issue
Block a user