diff --git a/nodes/__init__.py b/nodes/__init__.py new file mode 100644 index 0000000..ef1a5b1 --- /dev/null +++ b/nodes/__init__.py @@ -0,0 +1,14 @@ +# Import mappings from individual node files + +from .prompt_multiple_styles_selector_nikosis import NODE_CLASS_MAPPINGS as PMSS_NODE_CLASS, NODE_DISPLAY_NAME_MAPPINGS as PMSS_NODE_DISPLAY +from .text_concatenate_nikosis import NODE_CLASS_MAPPINGS as TC_NODE_CLASS, NODE_DISPLAY_NAME_MAPPINGS as TC_NODE_DISPLAY +from .aspect_ratio_nikosis import NODE_CLASS_MAPPINGS as AR_NODE_CLASS, NODE_DISPLAY_NAME_MAPPINGS as AR_NODE_DISPLAY + +# Combine all node class mappings into a single dictionary +NODE_CLASS_MAPPINGS = { **PMSS_NODE_CLASS, **TC_NODE_CLASS, **AR_NODE_CLASS } + + +# Combine all node display name mappings into a single dictionary +NODE_DISPLAY_NAME_MAPPINGS = { **PMSS_NODE_DISPLAY, **TC_NODE_DISPLAY, **AR_NODE_DISPLAY } + +__all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS'] diff --git a/nodes/aspect_ratio_nikosis.py b/nodes/aspect_ratio_nikosis.py new file mode 100644 index 0000000..c732614 --- /dev/null +++ b/nodes/aspect_ratio_nikosis.py @@ -0,0 +1,85 @@ +# ComfyUI/custom_nodes/ComfyUI-Nikosis-Nodes/nodes/aspect_ration_nikosis.py + +import os +import torch + +NODE_FILE = os.path.abspath(__file__) +CUSTOM_NODE_ROOT = os.path.dirname(os.path.dirname(NODE_FILE)) # Up to .../ComfyUI-Nikosis-Nodes/ + +MANIFEST = { + "name": "Aspect Ratio (nikosis)", + "version": (1, 0, 0), + "author": "Nikosis", + "project": "https://github.com/Nikosis/ComfyUI-Nikosis-Nodes", + "description": "A custom ComfyUI node to generate an aspect ratio", +} + +class Aspect_Ratio_Nikosis: + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + + aspect_ratios = ["custom", + "1:1 square 1024x1024", + "3:4 portrait 896x1152", + "5:8 portrait 832x1216", + "9:16 portrait 768x1344", + "9:21 portrait 640x1536", + "4:3 landscape 1152x896", + "3:2 landscape 1216x832", + "16:9 landscape 1344x768", + "21:9 landscape 1536x640"] + + return { + "required": { + "width": ("INT", {"default": 1024, "min": 64, "max": 8192}), + "height": ("INT", {"default": 1024, "min": 64, "max": 8192}), + "aspect_ratio": (aspect_ratios,), + "swap_dimensions": (["Off", "On"],), + "upscale_factor": ("FLOAT", {"default": 1.0, "min": 0.1, "max": 100.0, "step":0.1}), + "batch_size": ("INT", {"default": 1, "min": 1, "max": 64}) + } + } + RETURN_TYPES = ("INT", "INT", "FLOAT", "INT", "LATENT", "STRING", ) + RETURN_NAMES = ("width", "height", "upscale_factor", "batch_size", "empty_latent", ) + FUNCTION = "aspect_ratio" + CATEGORY = "Nikosis/Aspect Ratio" + + def Aspect_Ratio(self, width, height, aspect_ratio, swap_dimensions, upscale_factor, batch_size): + if aspect_ratio == "1:1 square 1024x1024": + width, height = 1024, 1024 + elif aspect_ratio == "3:4 portrait 896x1152": + width, height = 896, 1152 + elif aspect_ratio == "5:8 portrait 832x1216": + width, height = 832, 1216 + elif aspect_ratio == "9:16 portrait 768x1344": + width, height = 768, 1344 + elif aspect_ratio == "9:21 portrait 640x1536": + width, height = 640, 1536 + elif aspect_ratio == "4:3 landscape 1152x896": + width, height = 1152, 896 + elif aspect_ratio == "3:2 landscape 1216x832": + width, height = 1216, 832 + elif aspect_ratio == "16:9 landscape 1344x768": + width, height = 1344, 768 + elif aspect_ratio == "21:9 landscape 1536x640": + width, height = 1536, 640 + + if swap_dimensions == "On": + width, height = height, width + + latent = torch.zeros([batch_size, 4, height // 8, width // 8]) + + return(width, height, upscale_factor, batch_size, {"samples":latent}, ) + +NODE_CLASS_MAPPINGS = { + "Aspect Ratio (nikosis)": Aspect_Ratio_Nikosis, +} + +NODE_DISPLAY_NAME_MAPPINGS = { + "Aspect Ratio (nikosis)": "🖌️ Aspect Ratio (nikosis)" +} + +__all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS'] diff --git a/nodes/prompt_multiple_styles_selector_nikosis.py b/nodes/prompt_multiple_styles_selector_nikosis.py new file mode 100644 index 0000000..391b51e --- /dev/null +++ b/nodes/prompt_multiple_styles_selector_nikosis.py @@ -0,0 +1,88 @@ +# ComfyUI/custom_nodes/ComfyUI-Nikosis-Nodes/nodes/prompt_multiple_styles_selector_nikosis.py + +import os +import json + +print("Loading prompt_multiple_styles_selector_nikosis.py from comfyui-nikosis-nodes") + +NODE_FILE = os.path.abspath(__file__) # e.g., .../nodes/prompt_multiple_styles_selector_nikosis.py +CUSTOM_NODE_ROOT = os.path.dirname(os.path.dirname(NODE_FILE)) # Up to .../ComfyUI-Nikosis-Nodes/ +CONFIG_DIR = os.path.join(CUSTOM_NODE_ROOT, "config") # .../ComfyUI-Nikosis-Nodes/config/ +STYLES_PATH = os.path.join(CONFIG_DIR, "styles.json") # .../ComfyUI-Nikosis-Nodes/config/styles.json +TEXT_TYPE = "STRING" + +MANIFEST = { + "name": "Prompt Multiple Styles Selector (nikosis)", + "version": (1, 0, 0), + "author": "Nikosis", + "project": "https://github.com/Nikosis/ComfyUI-Nikosis-Nodes", + "description": "A custom ComfyUI node to select and combine multiple prompt styles from a styles.json file with dropdowns", +} + +if not os.path.exists(CONFIG_DIR): + os.makedirs(CONFIG_DIR, exist_ok=True) + +class Prompt_Multiple_Styles_Selector_Nikosis: + @classmethod + def INPUT_TYPES(cls): + style_options = ["No Style"] + if os.path.exists(STYLES_PATH): + with open(STYLES_PATH, 'r') as f: + styles = json.load(f) + style_options.extend(list(styles.keys())) + + return { + "required": { + "style1": (style_options, {"default": "No Style"}), + "style2": (style_options, {"default": "No Style"}), + "style3": (style_options, {"default": "No Style"}), + "style4": (style_options, {"default": "No Style"}), + } + } + + RETURN_TYPES = (TEXT_TYPE, TEXT_TYPE) + RETURN_NAMES = ("positive_prompt", "negative_prompt") + FUNCTION = "multi_style_prompt" + CATEGORY = "Nikosis/Text" + + def __init__(self): + self.styles = None + self.styles_path = STYLES_PATH + + def multi_style_prompt(self, style1="No Style", style2="No Style", style3="No Style", style4="No Style"): + if self.styles is None and os.path.exists(self.styles_path): + with open(self.styles_path, 'r') as f: + self.styles = json.load(f) + if self.styles is None: + return ("", "") + + selected_styles = [style1, style2, style3, style4] + if all(s == "No Style" for s in selected_styles): + return ("", "") + + pos_prompts = [] + neg_prompts = [] + + for style in selected_styles: + if style in self.styles and style != "No Style": + pos_prompt = self.styles[style].get("prompt", "") + neg_prompt = self.styles[style].get("negative_prompt", "") + if pos_prompt: + pos_prompts.append(pos_prompt) + if neg_prompt: + neg_prompts.append(neg_prompt) + + positive_prompt = ", ".join(pos_prompts) + negative_prompt = ", ".join(neg_prompts) + + return (positive_prompt, negative_prompt) + +NODE_CLASS_MAPPINGS = { + "Prompt Multiple Styles Selector (nikosis)": Prompt_Multiple_Styles_Selector_Nikosis +} + +NODE_DISPLAY_NAME_MAPPINGS = { + "Prompt Multiple Styles Selector (nikosis)": "🖌️ Prompt Multiple Style Selector (nikosis)" +} + +__all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS'] diff --git a/nodes/text_concatenate_nikosis.py b/nodes/text_concatenate_nikosis.py new file mode 100644 index 0000000..532d1a9 --- /dev/null +++ b/nodes/text_concatenate_nikosis.py @@ -0,0 +1,81 @@ +# ComfyUI/custom_nodes/ComfyUI-Nikosis-Nodes/nodes/text_concatenate_nikosis.py + +import os + +NODE_FILE = os.path.abspath(__file__) +CUSTOM_NODE_ROOT = os.path.dirname(os.path.dirname(NODE_FILE)) # Up to .../ComfyUI-Nikosis-Nodes/ +TEXT_TYPE = "STRING" + +MANIFEST = { + "name": "Text Concatenate (nikosis)", + "version": (1, 0, 0), + "author": "Nikosis", + "project": "https://github.com/Nikosis/ComfyUI-Nikosis-Nodes", + "description": "A custom ComfyUI node to concatenate multiple text inputs with a delimiter and whitespace cleaning option", +} + +class Text_Concatenate_Nikosis: + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "text_a": ("STRING", {"forceInput": True, "default": ""}), + "text_b": ("STRING", {"forceInput": True, "default": ""}), + "delimiter": ("STRING", {"default": ", ", "multiline": False}), + "clean_whitespace": (["true", "false"], {"default": "true"}), + }, + "optional": { + "text_c": ("STRING", {"default": ""}), + "text_d": ("STRING", {"default": ""}), + } + } + + RETURN_TYPES = ("STRING",) + FUNCTION = "text_concatenate" + CATEGORY = "Nikosis/Text" + + def text_concatenate(self, text_a, text_b, delimiter, clean_whitespace, **kwargs): + # Silently default to "true" if clean_whitespace is invalid + if clean_whitespace not in ["true", "false"]: + clean_whitespace = "true" + + text_inputs = [] + + # Handle special case for newline delimiter + if delimiter in ("\n", "\\n"): + delimiter = "\n" + + # Process required inputs + if clean_whitespace == "true": + text_a = text_a.strip() if text_a else "" + text_b = text_b.strip() if text_b else "" + if text_a: + text_inputs.append(text_a) + if text_b: + text_inputs.append(text_b) + + # Process optional inputs + for k in sorted(kwargs.keys()): + v = kwargs[k] + if isinstance(v, str): + if clean_whitespace == "true": + v = v.strip() + if v: + text_inputs.append(v) + + # Join and return + merged_text = delimiter.join(text_inputs) + return (merged_text,) + +NODE_CLASS_MAPPINGS = { + "Text Concatenate (nikosis)": Text_Concatenate_Nikosis, +} + +NODE_DISPLAY_NAME_MAPPINGS = { + "Text Concatenate (nikosis)": "🖌️ Text Concatenate (nikosis)" +} + +__all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS'] \ No newline at end of file