diff --git a/nodes/__init__.py b/nodes/__init__.py new file mode 100644 index 0000000..58785e3 --- /dev/null +++ b/nodes/__init__.py @@ -0,0 +1,4 @@ +# ComfyUI Selectors Nodes Package + +# Define MAX_RESOLUTION for nodes that need it +MAX_RESOLUTION = 8192 diff --git a/nodes/height_node.py b/nodes/height_node.py new file mode 100644 index 0000000..8a6aebc --- /dev/null +++ b/nodes/height_node.py @@ -0,0 +1,49 @@ +from nodes import MAX_RESOLUTION + + +class HeightNode: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "height": ( + "INT", + { + "default": 512, + "min": 64, + "max": MAX_RESOLUTION, + "step": 8, + "tooltip": "Image height in pixels (must be multiple of 8)", + }, + ), + "preset": ( + [ + "custom", + "512", + "768", + "1024", + "1152", + "1216", + "1344", + "1408", + "1472", + "1536", + ], + { + "default": "custom", + "tooltip": "Common height presets for quick selection", + }, + ), + } + } + + RETURN_TYPES = ("INT",) + RETURN_NAMES = ("height",) + FUNCTION = "get_height" + CATEGORY = "comfyassets/Dimensions" + + def get_height(self, height, preset): + """Get height value, using preset if not custom.""" + if preset != "custom": + height = int(preset) + return (height,) diff --git a/nodes/sampler_selector.py b/nodes/sampler_selector.py new file mode 100644 index 0000000..c2c83bd --- /dev/null +++ b/nodes/sampler_selector.py @@ -0,0 +1,26 @@ +import comfy.samplers + + +class SamplerSelector: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "sampler_name": ( + comfy.samplers.KSampler.SAMPLERS, + { + "default": "euler", + "tooltip": "The sampling algorithm to use for generation", + }, + ), + } + } + + RETURN_TYPES = (comfy.samplers.KSampler.SAMPLERS,) + RETURN_NAMES = ("sampler_name",) + FUNCTION = "select_sampler" + CATEGORY = "comfyassets/Sampling" + + def select_sampler(self, sampler_name): + """Select and return sampler name for use in other nodes.""" + return (sampler_name,) diff --git a/nodes/scheduler_selector.py b/nodes/scheduler_selector.py new file mode 100644 index 0000000..3e8b900 --- /dev/null +++ b/nodes/scheduler_selector.py @@ -0,0 +1,26 @@ +import comfy.samplers + + +class SchedulerSelector: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "scheduler": ( + comfy.samplers.KSampler.SCHEDULERS, + { + "default": "normal", + "tooltip": "The scheduler algorithm to control sampling step distribution", # noqa: E501 + }, + ), + } + } + + RETURN_TYPES = (comfy.samplers.KSampler.SCHEDULERS,) + RETURN_NAMES = ("scheduler",) + FUNCTION = "select_scheduler" + CATEGORY = "comfyassets/Sampling" + + def select_scheduler(self, scheduler): + """Select and return scheduler name for use in other nodes.""" + return (scheduler,) diff --git a/nodes/seed_generator.py b/nodes/seed_generator.py new file mode 100644 index 0000000..ed050d5 --- /dev/null +++ b/nodes/seed_generator.py @@ -0,0 +1,43 @@ +import random + + +class SeedGenerator: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "seed": ( + "INT", + { + "default": 0, + "min": 0, + "max": 0xFFFFFFFFFFFFFFFF, + "tooltip": "Seed value for reproducible generation. Use 0 with randomize for random seeds.", # noqa: E501 + }, + ), + "control_after_generate": ( + ["fixed", "increment", "decrement", "randomize"], + { + "default": "randomize", + "tooltip": "How to handle seed after generation", + }, + ), + } + } + + RETURN_TYPES = ("INT",) + RETURN_NAMES = ("seed",) + FUNCTION = "generate_seed" + CATEGORY = "comfyassets/Generation" + + def generate_seed(self, seed, control_after_generate): + """Generate and return seed value for use in other nodes.""" + if control_after_generate == "randomize": + seed = random.randint(0, 0xFFFFFFFFFFFFFFFF) + elif control_after_generate == "increment": + seed = (seed + 1) % (0xFFFFFFFFFFFFFFFF + 1) + elif control_after_generate == "decrement": + seed = (seed - 1) % (0xFFFFFFFFFFFFFFFF + 1) + # "fixed" mode returns the seed as-is + + return (seed,) diff --git a/nodes/width_height_node.py b/nodes/width_height_node.py new file mode 100644 index 0000000..6a48023 --- /dev/null +++ b/nodes/width_height_node.py @@ -0,0 +1,77 @@ +from nodes import MAX_RESOLUTION + + +class WidthHeightNode: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "width": ( + "INT", + { + "default": 512, + "min": 64, + "max": MAX_RESOLUTION, + "step": 8, + "tooltip": "Image width in pixels (must be multiple of 8)", + }, + ), + "height": ( + "INT", + { + "default": 512, + "min": 64, + "max": MAX_RESOLUTION, + "step": 8, + "tooltip": "Image height in pixels (must be multiple of 8)", + }, + ), + "preset": ( + [ + "custom", + "512x512", + "768x512", + "1024x768", + "1152x896", + "1216x832", + "1344x768", + "1408x704", + "1472x704", + "1536x640", + "640x1536", + "704x1472", + "704x1408", + "768x1344", + "832x1216", + "896x1152", + "768x1024", + "512x768", + ], + { + "default": "custom", + "tooltip": "Common dimension presets for quick selection", + }, + ), + "swap_dimensions": ( + "BOOLEAN", + {"default": False, "tooltip": "Swap width and height values"}, + ), + } + } + + RETURN_TYPES = ("INT", "INT") + RETURN_NAMES = ("width", "height") + FUNCTION = "get_dimensions" + CATEGORY = "comfyassets/Dimensions" + + def get_dimensions(self, width, height, preset, swap_dimensions): + """Get width and height values with preset and swap support.""" + if preset != "custom": + preset_parts = preset.split("x") + width = int(preset_parts[0]) + height = int(preset_parts[1]) + + if swap_dimensions: + width, height = height, width + + return (width, height) diff --git a/nodes/width_node.py b/nodes/width_node.py new file mode 100644 index 0000000..a588c04 --- /dev/null +++ b/nodes/width_node.py @@ -0,0 +1,49 @@ +from nodes import MAX_RESOLUTION + + +class WidthNode: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "width": ( + "INT", + { + "default": 512, + "min": 64, + "max": MAX_RESOLUTION, + "step": 8, + "tooltip": "Image width in pixels (must be multiple of 8)", + }, + ), + "preset": ( + [ + "custom", + "512", + "768", + "1024", + "1152", + "1216", + "1344", + "1408", + "1472", + "1536", + ], + { + "default": "custom", + "tooltip": "Common width presets for quick selection", + }, + ), + } + } + + RETURN_TYPES = ("INT",) + RETURN_NAMES = ("width",) + FUNCTION = "get_width" + CATEGORY = "comfyassets/Dimensions" + + def get_width(self, width, preset): + """Get width value, using preset if not custom.""" + if preset != "custom": + width = int(preset) + return (width,)