Files
jakechai-ComfyUI-JakeUpgrade/nodes/jake_node_misc.py
T

836 lines
32 KiB
Python

#---------------------------------------------------------------------------------------------------------------------#
# Jake Upgrade Misc Nodes for JK Custom Workflow of ComfyUI
#---------------------------------------------------------------------------------------------------------------------#
import random
import json
import os
import comfy.samplers
from typing import Any, Tuple, List, Dict
from .jake_tools import any_type, get_resolution, get_sd3_resolution
from .jake_utils import multiple_of_int, parse_string_list
from ..categories import icons
#---------------------------------------------------------------------------------------------------------------------#
# Project & Settings Nodes
#---------------------------------------------------------------------------------------------------------------------#
class ProjectSetting_JK:
"""Project settings for workflow organization with customizable naming patterns"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"project_name": ("STRING", {
"default": 'myproject',
"multiline": False,
"tooltip": "Name of the project for organization"
}),
"image_name": ("STRING", {
"default": f'v%counter_%seed_%time',
"multiline": False,
"tooltip": "Image naming pattern (supports %counter, %seed, %time variables)"
}),
"path_name": ("STRING", {
"default": f'%date',
"multiline": False,
"tooltip": "Path naming pattern (supports %date variable)"
}),
"seed": ("INT", {
"default": 0,
"min": 0,
"max": 0xffffffffffffffff,
"tooltip": "Random seed for project"
}),
},
}
RETURN_TYPES = ("STRING", "STRING", "INT")
RETURN_NAMES = ("Image_Name", "Path_Name", "Counter")
FUNCTION = "get_value"
CATEGORY = icons.get("JK/Misc")
DESCRIPTION = "Project settings for workflow organization with customizable naming patterns."
def get_value(self, project_name: str, image_name: str, path_name: str, seed: int) -> Tuple[str, str, int]:
"""Get project settings values with pattern processing"""
# Combine project name with patterns
processed_image_name = project_name + "_" + image_name
processed_path_name = project_name + "/" + path_name
# Initialize random seed for counter generation
random.seed(seed)
number = random.randint(0, 18446744073709551615)
return (processed_image_name, processed_path_name, seed)
class KsamplerParametersDefault_JK:
"""Default parameters for KSampler (steps, CFG scale, denoise strength)"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"steps": ("INT", {
"default": 20,
"min": 1,
"max": 10000,
"tooltip": "Number of sampling steps"
}),
"cfg": ("FLOAT", {
"default": 8.0,
"min": 0.0,
"max": 100.0,
"step": 0.05,
"tooltip": "Classifier-Free Guidance scale"
}),
"denoise": ("FLOAT", {
"default": 1.0,
"min": 0.0,
"max": 1.0,
"step": 0.01,
"tooltip": "Denoising strength (1.0 = full denoise)"
}),
},
}
RETURN_TYPES = ("INT", "FLOAT", "FLOAT")
RETURN_NAMES = ("STEPS", "CFG", "DENOISE")
FUNCTION = "get_value"
CATEGORY = icons.get("JK/Misc")
DESCRIPTION = "Default parameters for KSampler (steps, CFG scale, denoise strength)."
def get_value(self, steps: int, cfg: float, denoise: float) -> Tuple[int, float, float]:
"""Get KSampler parameter values"""
return (steps, cfg, denoise)
class KsamplerAdvParametersDefault_JK:
"""Advanced KSampler parameters for step control and scheduling"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"switch_at_step": ("INT", {
"default": 10,
"min": 1,
"max": 10000,
"tooltip": "Step at which to switch samplers or settings"
}),
},
}
RETURN_TYPES = ("INT", "INT", "INT", "STRING", "STRING")
RETURN_NAMES = ("start_at_step", "switch_at_step", "end_at_step", "enable", "disable")
FUNCTION = "get_value"
CATEGORY = icons.get("JK/Misc")
DESCRIPTION = "Advanced KSampler parameters for step control and scheduling."
def get_value(self, switch_at_step: int) -> Tuple[int, int, int, str, str]:
"""Get advanced KSampler parameter values with step ranges"""
return (0, switch_at_step, 10000, "enable", "disable")
class BaseModelParametersSD3API_JK:
"""SD3 API compatible base model parameters with prompt management"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"positive": ("STRING", {
"default": '',
"multiline": True,
"tooltip": "Positive prompt text"
}),
"negative": ("STRING", {
"default": '',
"multiline": True,
"tooltip": "Negative prompt text"
}),
"use_input_prompt": ("BOOLEAN", {
"default": False,
"tooltip": "Enable to use input prompts instead of default prompts"
}),
"aspect_ratio": (["1:1", "5:4", "3:2", "16:9", "21:9", "4:5", "2:3", "9:16", "9:21"], {
"tooltip": "Aspect ratio for SD3 model"
}),
},
"optional": {
"input_positive": ("STRING", {
"default": '',
"tooltip": "Optional positive prompt input (used when use_input_prompt is enabled)"
}),
"input_negative": ("STRING", {
"default": '',
"tooltip": "Optional negative prompt input (used when use_input_prompt is enabled)"
}),
},
}
RETURN_TYPES = ("STRING", "STRING", "STRING", "INT", "INT")
RETURN_NAMES = ("POSITIVE", "NEGATIVE", "ASPECT_RATIO", "WIDTH", "HEIGHT")
FUNCTION = "get_value"
CATEGORY = icons.get("JK/Misc")
DESCRIPTION = "SD3 API compatible base model parameters with prompt management and aspect ratio selection."
DEPRECATED = True
def get_value(self, positive: str, negative: str, use_input_prompt: bool, aspect_ratio: str,
input_positive: str = None, input_negative: str = None) -> Tuple[str, str, str, int, int]:
"""Get SD3 model parameters with optional input prompt override"""
# Use input prompts if enabled and provided
if use_input_prompt:
if input_positive is not None and input_positive != "":
positive = input_positive
if input_negative is not None and input_negative != "":
negative = input_negative
# Get resolution from aspect ratio
try:
from .jake_tools import get_sd3_resolution
width, height = get_sd3_resolution(aspect_ratio)
except ImportError:
# Fallback to default resolution if function not available
width, height = 1024, 1024
return (positive, negative, aspect_ratio, width, height)
class Inject_Noise_Params_JK:
"""Parameters for noise injection with seed and strength control"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"noise_seed": ("INT", {
"default": 0,
"min": 0,
"max": 0xffffffffffffffff,
"tooltip": "Seed for noise generation"
}),
"noise_strength": ("FLOAT", {
"default": 1.0,
"min": -20.0,
"max": 20.0,
"step": 0.01,
"round": 0.01,
"tooltip": "Strength of noise injection"
}),
"normalize": (["false", "true"], {
"default": "false",
"tooltip": "Whether to normalize the noise"
}),
},
}
RETURN_TYPES = ("INT", "FLOAT", ["false", "true"])
RETURN_NAMES = ("Seed", "Strength", "Normalize")
FUNCTION = "get_value"
CATEGORY = icons.get("JK/Misc")
DESCRIPTION = "Parameters for noise injection with seed and strength control."
def get_value(self, noise_seed: int, noise_strength: float, normalize: str) -> Tuple[int, float, str]:
"""Get noise injection parameters"""
return (noise_seed, noise_strength, normalize)
class SD3_Prompts_Switch_JK:
"""Switch between different prompt types for SD3 (CLIP-L, CLIP-G, T5-XXL)"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"clip_l": ("STRING", {
"default": '',
"multiline": True,
"tooltip": "CLIP-L prompt text"
}),
"clip_g": ("STRING", {
"default": '',
"multiline": True,
"tooltip": "CLIP-G prompt text"
}),
"t5xxl": ("STRING", {
"default": '',
"multiline": True,
"tooltip": "T5-XXL prompt text"
}),
"clip_l_prompt": (["clip_l", "clip_g", "t5xxl"], {
"default": "clip_l",
"tooltip": "Prompt type to use for CLIP-L output"
}),
"clip_g_prompt": (["clip_l", "clip_g", "t5xxl"], {
"default": "clip_g",
"tooltip": "Prompt type to use for CLIP-G output"
}),
"t5xxl_prompt": (["clip_l", "clip_g", "t5xxl"], {
"default": "t5xxl",
"tooltip": "Prompt type to use for T5-XXL output"
}),
},
}
RETURN_TYPES = ("STRING", "STRING", "STRING")
RETURN_NAMES = ("clip_l", "clip_g", "t5xxl")
FUNCTION = "get_value"
CATEGORY = icons.get("JK/Misc")
DESCRIPTION = "Switch between different prompt types for SD3 (CLIP-L, CLIP-G, T5-XXL)."
def get_value(self, clip_l: str, clip_g: str, t5xxl: str, clip_l_prompt: str,
clip_g_prompt: str, t5xxl_prompt: str) -> Tuple[str, str, str]:
"""Switch prompts between different SD3 prompt types"""
_clip_l = self._select_prompt(clip_l, clip_g, t5xxl, clip_l_prompt)
_clip_g = self._select_prompt(clip_l, clip_g, t5xxl, clip_g_prompt)
_t5xxl = self._select_prompt(clip_l, clip_g, t5xxl, t5xxl_prompt)
return (_clip_l, _clip_g, _t5xxl)
def _select_prompt(self, clip_l: str, clip_g: str, t5xxl: str, prompt_type: str) -> str:
"""Select prompt based on type"""
if prompt_type == "clip_l":
return clip_l
elif prompt_type == "clip_g":
return clip_g
else: # t5xxl
return t5xxl
class SDXL_TargetRes_JK:
"""Target resolution calculator for SDXL with scaling support"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"width": ("INT", {
"default": 1024,
"tooltip": "Original width to scale from"
}),
"height": ("INT", {
"default": 1024,
"tooltip": "Original height to scale from"
}),
"target_res_scale": ("FLOAT", {
"default": 1.0,
"min": 0.01,
"max": 16.0,
"step": 0.01,
"tooltip": "Scale factor for target resolution"
}),
},
}
RETURN_TYPES = ("INT", "INT")
RETURN_NAMES = ("target_width", "target_height")
FUNCTION = "get_value"
CATEGORY = icons.get("JK/Misc")
DESCRIPTION = "Target resolution calculator for SDXL with scaling support"
DEPRECATED = True
def get_value(self, width: int, height: int, target_res_scale: float) -> Tuple[int, int]:
"""Calculate target resolution with scaling and multiple-of-8 alignment"""
target_width = multiple_of_int(width * target_res_scale, 8)
target_height = multiple_of_int(height * target_res_scale, 8)
return (target_width, target_height)
class GuidanceDefault_JK:
"""Default guidance scale value for model conditioning"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"guidance": ("FLOAT", {
"default": 3.5,
"min": 0.0,
"max": 100.0,
"step": 0.1,
"tooltip": "Guidance scale for model conditioning"
}),
},
}
RETURN_TYPES = ("FLOAT",)
RETURN_NAMES = ("GUIDANCE",)
FUNCTION = "get_value"
CATEGORY = icons.get("JK/Misc")
DESCRIPTION = "Default guidance scale value for model conditioning."
def get_value(self, guidance: float) -> Tuple[float]:
"""Get guidance scale value"""
return (guidance,)
class ImageResizeMode_JK:
"""Image resize mode selection for various resizing strategies"""
RESIZE_MODES = ["Just Resize", "Crop and Resize", "Resize and Fill"]
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"resize_mode": (cls.RESIZE_MODES, {
"default": "Just Resize",
"tooltip": "Method for resizing images"
})
}
}
RETURN_TYPES = ("STRING",)
RETURN_NAMES = ("MODE",)
FUNCTION = "execute"
CATEGORY = icons.get("JK/Misc")
DESCRIPTION = "Image resize mode selection for various resizing strategies."
def execute(self, resize_mode: str) -> Tuple[str]:
"""Get resize mode value"""
return (resize_mode,)
class SamplerLoader_JK:
"""Sampler and scheduler selection with name output"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"sampler": (comfy.samplers.KSampler.SAMPLERS, {
"tooltip": "Sampling algorithm selection"
}),
"scheduler": (comfy.samplers.KSampler.SCHEDULERS, {
"tooltip": "Scheduling algorithm selection"
}),
}
}
RETURN_TYPES = ("STRING", comfy.samplers.KSampler.SAMPLERS, "STRING", comfy.samplers.KSampler.SCHEDULERS)
RETURN_NAMES = ("sampler_name", "Sampler", "schedular_name", "Schedular")
FUNCTION = "list"
CATEGORY = icons.get("JK/Misc")
DESCRIPTION = "Sampler and scheduler selection with name output."
def list(self, sampler: str, scheduler: str) -> Tuple[str, str, str, str]:
"""Get sampler and scheduler with names"""
return (sampler, sampler, scheduler, scheduler)
class UpscaleMethod_JK:
"""Upscale method selection for images and latents"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"image_upscale_method": (["nearest-exact", "bilinear", "area", "bicubic", "lanczos"], {
"default": "lanczos",
"tooltip": "Upscaling method for images"
}),
"latent_upscale_method": (["nearest-exact", "bilinear", "area", "bicubic", "bislerp"], {
"default": "bilinear",
"tooltip": "Upscaling method for latent representations"
}),
},
}
RETURN_TYPES = ("STRING", "STRING")
RETURN_NAMES = ("image_upscale_method", "latent_upscale_method")
FUNCTION = "get_value"
CATEGORY = icons.get("JK/Misc")
DESCRIPTION = "Upscale method selection for images and latents."
def get_value(self, image_upscale_method: str, latent_upscale_method: str) -> Tuple[str, str]:
"""Get upscale method values"""
return (image_upscale_method, latent_upscale_method)
#---------------------------------------------------------------------------------------------------------------------#
# Resolution & Aspect Ratio Nodes
#---------------------------------------------------------------------------------------------------------------------#
class CR_AspectRatio_JK:
"""Aspect ratio selector for various model types with custom resolution support"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"resolution": ([
"Custom", "SD15 512x512", "SD15 680x512", "SD15 768x512", "SD15 912x512", "SD15 952x512", "SD15 1024x512",
"SD15 1224x512", "SD15 768x432", "SD15 768x416", "SD15 768x384", "SD15 768x320",
"SDXL 1024x1024", "SDXL 1024x960", "SDXL 1088x960", "SD3 1088x896", "SDXL 1152x896", "SDXL 1152x832", "SD3 1216x832", "SDXL 1280x768",
"QWen 1328x1328", "QWen 1328x800", "SD3 1344x768", "SDXL 1344x704", "SDXL 1408x704", "SDXL 1472x704", "SD3 1536x640", "SDXL 1600x640", "SDXL 1664x576", "SDXL 1728x576", "QWen 1920x1080"
], {
"tooltip": "Predefined resolution presets for different models"
}),
"custom_width": ("INT", {
"default": 512,
"min": 64,
"max": 16384,
"step": 8,
"tooltip": "Custom width when resolution is set to Custom"
}),
"custom_height": ("INT", {
"default": 512,
"min": 64,
"max": 16384,
"step": 8,
"tooltip": "Custom height when resolution is set to Custom"
}),
"swap_dimensions": ("BOOLEAN", {
"default": False,
"tooltip": "Swap width and height dimensions"
}),
}
}
RETURN_TYPES = ("INT", "INT",)
RETURN_NAMES = ("width", "height")
FUNCTION = "Aspect_Ratio"
CATEGORY = icons.get("JK/Misc")
DESCRIPTION = "Aspect ratio selector for various model types with custom resolution support."
def Aspect_Ratio(self, custom_width: int, custom_height: int, resolution: str, swap_dimensions: bool) -> Tuple[int, int]:
"""Calculate aspect ratio dimensions based on selection"""
if resolution == "Custom":
width, height = custom_width, custom_height
else:
try:
width, height = get_resolution(resolution)
except Exception as e:
# Fallback to default resolution if get_resolution fails
print(f"Warning: Failed to get resolution for {resolution}: {e}. Using default 512x512.")
width, height = 512, 512
if swap_dimensions:
return (height, width)
else:
return (width, height)
#---------------------------------------------------------------------------------------------------------------------#
# String & Data Processing Nodes
#---------------------------------------------------------------------------------------------------------------------#
# copied from https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Conversion-Nodes#cr-string-to-combo
class StringToCombo_JK:
"""Convert comma-separated string to combo selection (first item)"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"string": ("STRING", {
"multiline": False,
"default": "",
"tooltip": "Comma-separated string to convert to combo"
}),
},
}
RETURN_TYPES = (any_type,)
RETURN_NAMES = ("any",)
FUNCTION = "convert"
CATEGORY = icons.get("JK/Misc")
DESCRIPTION = "Convert comma-separated string to combo selection (first item)."
def convert(self, string: str) -> Tuple[Any]:
"""Convert string to combo value (first item in comma-separated list)"""
text_list = list()
if string != "":
values = string.split(',')
text_list = values[0].strip() # Take first item and strip whitespace
return (text_list,)
class GetNthString_JK:
"""Get nth item from comma-separated string list with type conversion"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"string_list": ("STRING", {
"default": "1.0, 2.0, 3.0",
"multiline": True,
"tooltip": "Comma-separated list of values"
}),
"index": ("INT", {
"default": 0,
"min": -1,
"max": 100,
"step": 1,
"display": "number",
"tooltip": "Index of item to retrieve (negative values count from end)"
}),
},
}
RETURN_TYPES = ("STRING", "INT", "FLOAT", "BOOLEAN")
RETURN_NAMES = ("string", "int", "float", "boolean")
FUNCTION = "process"
CATEGORY = icons.get("JK/Misc")
DESCRIPTION = "Get nth item from comma-separated string list with type conversion."
OUTPUT_NODE = False
def process(self, string_list: str, index: int) -> Tuple[str, int, float, bool]:
"""Get nth item from string list with automatic type conversion"""
try:
items = parse_string_list(string_list)
except Exception as e:
raise ValueError(f"Error parsing string list: {str(e)}")
# Handle negative indices (counting from end)
if index < 0:
index = len(items) + index
# Check index bounds
if index < 0 or index >= len(items):
raise ValueError(f"Index {index} out of range (0-{len(items)-1})")
selected_str = items[index]
# Type conversions with error handling
try:
int_val = int(selected_str)
except ValueError:
int_val = 0
try:
float_val = float(selected_str)
except ValueError:
float_val = 0.0
# Boolean conversion with common truthy/falsy values
lower_str = selected_str.lower().strip()
if lower_str in ("true", "1", "yes", "y", "on"):
bool_val = True
elif lower_str in ("false", "0", "no", "n", "off"):
bool_val = False
else:
bool_val = bool(selected_str)
return (selected_str, int_val, float_val, bool_val)
#---------------------------------------------------------------------------------------------------------------------#
# JSON Data Nodes
#---------------------------------------------------------------------------------------------------------------------#
class SaveStringListToJSON_JK:
"""Save string data to JSON file with overwrite control"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"string_input": ("STRING", {
"default": '',
"tooltip": "String data to save to JSON file"
}),
"file_path": ("STRING", {
"default": '',
"tooltip": "Full path to JSON file for saving"
}),
"overwrite": ("BOOLEAN", {
"default": True,
"tooltip": "Overwrite existing file if True, skip if False"
}),
},
}
RETURN_TYPES = ("STRING",)
RETURN_NAMES = ("string_output",)
FUNCTION = "save_strlist"
CATEGORY = icons.get("JK/Misc")
DESCRIPTION = "Save string data to JSON file with overwrite control and directory creation."
def save_strlist(self, string_input: str, file_path: str, overwrite: bool) -> Tuple[str]:
"""Save string data to JSON file with error handling"""
# Check if file path is empty
if not file_path:
print("Error: file_path is empty. Cannot save JSON.")
return ("",)
# Check if file exists and overwrite is disabled
if os.path.exists(file_path) and not overwrite:
print(f"File '{file_path}' already exists and overwrite is set to False. Skipping save.")
return (string_input,)
# Ensure directory exists
parent_dir = os.path.dirname(file_path)
if parent_dir and not os.path.exists(parent_dir):
try:
os.makedirs(parent_dir, exist_ok=True)
print(f"Created directory: {parent_dir}")
except Exception as e:
print(f"Error creating directory {parent_dir}: {e}")
return (string_input,)
# Save to file with proper error handling
try:
with open(file_path, 'w', encoding='utf-8') as file:
json.dump(string_input, file, indent=4, ensure_ascii=False)
print(f"Successfully saved JSON to {file_path}")
except Exception as e:
print(f"Error saving JSON to {file_path}: {e}")
return (string_input,)
return (string_input,)
class LoadStringListFromJSON_JK:
"""Load string data from JSON file with caching and force reload options"""
def __init__(self):
self._cached_file_path = None
self._cached_file_hash = None
self._cached_data = None
self._last_force_reload_value = 0
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"file_path": ("STRING", {
"default": '',
"tooltip": "Full path to JSON file for loading"
}),
},
"optional": {
"force_reload": ("INT", {
"default": 0,
"min": 0,
"max": 100000,
"tooltip": "Force reload when value changes (useful for triggering reloads)"
}),
}
}
RETURN_TYPES = ("STRING",)
RETURN_NAMES = ("string_output",)
FUNCTION = "load_strlist"
CATEGORY = icons.get("JK/Misc")
DESCRIPTION = "Load string data from JSON file with caching and force reload options."
def load_strlist(self, file_path: str, force_reload: int = 0) -> Tuple[str]:
"""Load string data from JSON file with intelligent caching"""
# Check if file path is empty
if not file_path:
print("Warning: file_path is empty. Returning empty JSON string.")
self._clear_cache()
return ("",)
# Check if file exists
if not os.path.exists(file_path):
print(f"Error: File not found at {file_path}. Returning empty JSON string.")
self._clear_cache()
return ("",)
# Calculate current file hash for change detection
try:
from .jake_tools import calculate_sha256
current_file_hash = calculate_sha256(file_path)
except ImportError:
# Fallback to file modification time if SHA256 not available
current_file_hash = str(os.path.getmtime(file_path))
# Check if reload is needed based on file changes or force_reload
if (file_path != self._cached_file_path or
current_file_hash != self._cached_file_hash or
force_reload != self._last_force_reload_value):
print(f"Loading JSON from {file_path} (reloaded due to change or force_reload).")
try:
with open(file_path, 'r', encoding='utf-8') as file:
str_lists = json.load(file)
# Handle string list format compatibility
if isinstance(str_lists, list) and all(isinstance(item, str) for item in str_lists):
try:
parsed_list = []
for s in str_lists:
# Try to parse each string as JSON, keep original if it fails
try:
parsed_list.append(json.loads(s))
except json.JSONDecodeError:
parsed_list.append(s)
str_lists = parsed_list
except Exception:
# Keep original if bulk parsing fails
pass
# Update cache with new data
self._cached_file_path = file_path
self._cached_file_hash = current_file_hash
self._cached_data = str_lists
self._last_force_reload_value = force_reload
except json.JSONDecodeError as e:
print(f"Error decoding JSON from {file_path}: {e}")
self._clear_cache()
return ("",)
except Exception as e:
print(f"An unexpected error occurred while reading {file_path}: {e}")
self._clear_cache()
return ("",)
else:
print(f"Using cached JSON data for {file_path} (no change detected).")
# Return cached data as JSON string
if self._cached_data is not None:
try:
return (json.dumps(self._cached_data, ensure_ascii=False),)
except Exception as e:
print(f"Error serializing cached data to JSON: {e}")
return ("",)
else:
return ("",)
def _clear_cache(self):
"""Clear cache data"""
self._cached_file_path = None
self._cached_file_hash = None
self._cached_data = None
#---------------------------------------------------------------------------------------------------------------------#
# Simple Utility Nodes
#---------------------------------------------------------------------------------------------------------------------#
class TilingMode_JK:
"""Tiling mode selection for image generation"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"tiling": (["enable", "x_only", "y_only", "disable"], {
"default": "disable",
"tooltip": "Tiling mode for image generation"
}),
},
}
RETURN_TYPES = ("STRING",)
RETURN_NAMES = ("TILING",)
FUNCTION = "get_value"
CATEGORY = icons.get("JK/Misc")
DESCRIPTION = "Tiling mode selection for image generation."
def get_value(self, tiling: str) -> Tuple[str]:
"""Get tiling mode value"""
return (tiling,)
class RemoveInput_JK:
"""Remove input and provide default values for any type"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {},
"optional": {},
}
RETURN_TYPES = (any_type, "BOOLEAN", "BOOLEAN")
RETURN_NAMES = ("any", "TRUE", "FALSE")
FUNCTION = "removeinput"
CATEGORY = icons.get("JK/Misc")
DESCRIPTION = "Remove input and provide default values for any type"
DEPRECATED = True
def removeinput(self) -> Tuple[Any, bool, bool]:
"""Remove input and return default values"""
return (None, True, False)