diff --git a/py/display_any.py b/py/display_any.py new file mode 100644 index 0000000..5a564e3 --- /dev/null +++ b/py/display_any.py @@ -0,0 +1,36 @@ +"""Display any data node.""" +import json +from .constants import get_category, get_name + + +class RgthreeDisplayAny: + """Display any data node.""" + + NAME = get_name('Display Any') + CATEGORY = get_category() + + @classmethod + def INPUT_TYPES(cls): # pylint: disable = invalid-name, missing-function-docstring + return { + "required": { + "source": ("*", {}), + }, + } + + RETURN_TYPES = () + FUNCTION = "main" + OUTPUT_NODE = True + + def main(self, source=None): + """Main.""" + value = 'None' + if source is not None: + try: + value = json.dumps(source) + except Exception: + try: + value = str(source) + except Exception: + value = 'source exists, but could not be serialized.' + + return {"ui": {"text": (value,)}} diff --git a/py/image_inset_crop.py b/py/image_inset_crop.py index 30487ce..5f5f29a 100644 --- a/py/image_inset_crop.py +++ b/py/image_inset_crop.py @@ -1,64 +1,93 @@ +"""Image Inset Crop, with percentages.""" from .log import log_node_info from .constants import get_category, get_name from nodes import MAX_RESOLUTION -def getNewBounds(width, height, left, right, top, bottom): - left = 0 + left - right = width - right - top = 0 + top - bottom = height - bottom - return (left, right, top, bottom) +def get_new_bounds(width, height, left, right, top, bottom): + """Returns the new bounds for an image with inset crop data.""" + left = 0 + left + right = width - right + top = 0 + top + bottom = height - bottom + return (left, right, top, bottom) + class RgthreeImageInsetCrop: + """Image Inset Crop, with percentages.""" - NAME = get_name('Image Inset Crop') - CATEGORY = get_category() + NAME = get_name('Image Inset Crop') + CATEGORY = get_category() - @classmethod - def INPUT_TYPES(s): - return { - "required": { - "image": ("IMAGE",), - "measurement": (['Pixels', 'Percentage'],), - "left": ("INT", {"default": 0, "min": 0, "max": MAX_RESOLUTION, "step": 8}), - "right": ("INT", {"default": 0, "min": 0, "max": MAX_RESOLUTION, "step": 8}), - "top": ("INT", {"default": 0, "min": 0, "max": MAX_RESOLUTION, "step": 8}), - "bottom": ("INT", {"default": 0, "min": 0, "max": MAX_RESOLUTION, "step": 8}), - }, - } + @classmethod + def INPUT_TYPES(cls): # pylint: disable = invalid-name, missing-function-docstring + return { + "required": { + "image": ("IMAGE",), + "measurement": (['Pixels', 'Percentage'],), + "left": ("INT", { + "default": 0, + "min": 0, + "max": MAX_RESOLUTION, + "step": 8 + }), + "right": ("INT", { + "default": 0, + "min": 0, + "max": MAX_RESOLUTION, + "step": 8 + }), + "top": ("INT", { + "default": 0, + "min": 0, + "max": MAX_RESOLUTION, + "step": 8 + }), + "bottom": ("INT", { + "default": 0, + "min": 0, + "max": MAX_RESOLUTION, + "step": 8 + }), + }, + } - RETURN_TYPES = ("IMAGE",) - FUNCTION = "crop" + RETURN_TYPES = ("IMAGE",) + FUNCTION = "crop" - def crop(self, measurement, left, right, top, bottom, image=None): + # pylint: disable = too-many-arguments + def crop(self, measurement, left, right, top, bottom, image=None): + """Does the crop.""" - _, height, width, _ = image.shape + _, height, width, _ = image.shape - if measurement == 'Percentage': - left = int(width - (width * (100-left) / 100)) - right = int(width - (width * (100-right) / 100)) - top = int(height - (height * (100-top) / 100)) - bottom = int(height - (height * (100-bottom) / 100)) + if measurement == 'Percentage': + left = int(width - (width * (100 - left) / 100)) + right = int(width - (width * (100 - right) / 100)) + top = int(height - (height * (100 - top) / 100)) + bottom = int(height - (height * (100 - bottom) / 100)) - # Snap to 8 pixels - left = left // 8 * 8 - right = right // 8 * 8 - top = top // 8 * 8 - bottom = bottom // 8 * 8 + # Snap to 8 pixels + left = left // 8 * 8 + right = right // 8 * 8 + top = top // 8 * 8 + bottom = bottom // 8 * 8 - if left == 0 and right == 0 and bottom == 0 and top == 0: - return (image,) + if left == 0 and right == 0 and bottom == 0 and top == 0: + return (image,) - inset_left, inset_right, inset_top, inset_bottom = getNewBounds(width, height, left, right, top, bottom) - if (inset_top > inset_bottom): - raise ValueError(f"Invalid cropping dimensions top ({inset_top}) exceeds bottom ({inset_bottom})") - if (inset_left > inset_right): - raise ValueError(f"Invalid cropping dimensions left ({inset_left}) exceeds right ({inset_right})") - - log_node_info(self.NAME, f'Cropping image {width}x{height} width inset by {inset_left},{inset_right}, and height inset by {inset_top}, {inset_bottom}') - image = image[:, inset_top:inset_bottom, inset_left:inset_right, :] - - return (image,) + inset_left, inset_right, inset_top, inset_bottom = get_new_bounds(width, height, left, right, + top, bottom) + if inset_top > inset_bottom: + raise ValueError( + f"Invalid cropping dimensions top ({inset_top}) exceeds bottom ({inset_bottom})") + if inset_left > inset_right: + raise ValueError( + f"Invalid cropping dimensions left ({inset_left}) exceeds right ({inset_right})") + log_node_info( + self.NAME, f'Cropping image {width}x{height} width inset by {inset_left},{inset_right}, ' + + f'and height inset by {inset_top}, {inset_bottom}') + image = image[:, inset_top:inset_bottom, inset_left:inset_right, :] + return (image,) diff --git a/py/power_prompt.py b/py/power_prompt.py index da05e42..d03aa4c 100644 --- a/py/power_prompt.py +++ b/py/power_prompt.py @@ -1,105 +1,94 @@ import os -import re from .log import log_node_warn, log_node_info, log_node_success from .constants import get_category, get_name +from .power_prompt_utils import get_and_strip_loras from nodes import LoraLoader, CLIPTextEncode import folder_paths -NODE_NAME=get_name('Power Prompt') - -def get_and_strip_loras(prompt, silent=False): - pattern=']*?)(?::(-?\d*(?:\.\d*)?))?>' - lora_paths=folder_paths.get_filename_list('loras') - lora_filenames_no_ext=[os.path.splitext(os.path.basename(x))[0] for x in lora_paths] - - matches = re.findall(pattern, prompt) - - loras=[] - for match in matches: - tag_filename=match[0] - strength=float(match[1] if len(match) > 1 and len(match[1]) else 1.0) - if strength == 0 and not silent: - log_node_info(NODE_NAME, f'Skipping "{tag_filename}" with strength of zero') - continue - - # Let's be flexible. If the lora filename in the tag doesn't have the extension or - # path prefix, let's still find and load it. - if tag_filename not in lora_paths: - found_tag_filename=None - for index, value in enumerate(lora_filenames_no_ext): - if value in tag_filename: - found_tag_filename=lora_paths[index] - break - if found_tag_filename: - # if not silent: - # log_node_info(NODE_NAME, f'Found "{found_tag_filename}" for "{tag_filename}" in prompt') - tag_filename=found_tag_filename - else: - if not silent: - log_node_warn(NODE_NAME, f'Lora "{tag_filename}" not found, skipping.') - continue - - loras.append({'lora':tag_filename, 'strength':strength}) - - return (re.sub(pattern, '', prompt), loras) - +NODE_NAME = get_name('Power Prompt') class RgthreePowerPrompt: - NAME = NODE_NAME - CATEGORY = get_category() + NAME = NODE_NAME + CATEGORY = get_category() - @classmethod - def INPUT_TYPES(cls): # pylint: disable = invalid-name, missing-function-docstring - SAVED_PROMPTS_FILES=folder_paths.get_filename_list('saved_prompts') - SAVED_PROMPTS_CONTENT=[] - for filename in SAVED_PROMPTS_FILES: - with open(folder_paths.get_full_path('saved_prompts', filename), 'r') as f: - SAVED_PROMPTS_CONTENT.append(f.read()) - return { - 'required': { - 'prompt': ('STRING', {'multiline': True}), - }, - 'optional': { - "opt_model": ("MODEL",), - "opt_clip": ("CLIP", ), - 'insert_lora': (['CHOOSE', 'DISABLE LORAS'] + [os.path.splitext(x)[0] for x in folder_paths.get_filename_list('loras')],), - 'insert_embedding': (['CHOOSE',] + [os.path.splitext(x)[0] for x in folder_paths.get_filename_list('embeddings')],), - 'insert_saved': (['CHOOSE',] + SAVED_PROMPTS_FILES,), - }, - 'hidden': { - 'values_insert_saved': (['CHOOSE'] + SAVED_PROMPTS_CONTENT,), - } - } + @classmethod + def INPUT_TYPES(cls): # pylint: disable = invalid-name, missing-function-docstring + SAVED_PROMPTS_FILES = folder_paths.get_filename_list('saved_prompts') + SAVED_PROMPTS_CONTENT = [] + for filename in SAVED_PROMPTS_FILES: + with open(folder_paths.get_full_path('saved_prompts', filename), 'r') as f: + SAVED_PROMPTS_CONTENT.append(f.read()) + return { + 'required': { + 'prompt': ('STRING', { + 'multiline': True + }), + }, + 'optional': { + "opt_model": ("MODEL",), + "opt_clip": ("CLIP",), + 'insert_lora': (['CHOOSE', 'DISABLE LORAS'] + + [os.path.splitext(x)[0] for x in folder_paths.get_filename_list('loras')],), + 'insert_embedding': ([ + 'CHOOSE', + ] + [os.path.splitext(x)[0] for x in folder_paths.get_filename_list('embeddings')],), + 'insert_saved': ([ + 'CHOOSE', + ] + SAVED_PROMPTS_FILES,), + }, + 'hidden': { + 'values_insert_saved': (['CHOOSE'] + SAVED_PROMPTS_CONTENT,), + } + } - RETURN_TYPES = ('CONDITIONING', 'MODEL', 'CLIP', 'STRING',) - RETURN_NAMES = ('CONDITIONING', 'MODEL', 'CLIP', 'TEXT',) - FUNCTION = 'main' + RETURN_TYPES = ( + 'CONDITIONING', + 'MODEL', + 'CLIP', + 'STRING', + ) + RETURN_NAMES = ( + 'CONDITIONING', + 'MODEL', + 'CLIP', + 'TEXT', + ) + FUNCTION = 'main' - def main(self, prompt, opt_model=None, opt_clip=None, insert_lora=None, insert_embedding=None, insert_saved=None, values_insert_saved=None): - if insert_lora == 'DISABLE LORAS': - prompt, loras = get_and_strip_loras(prompt, True) - log_node_info(NODE_NAME, f'Disabling all found loras ({len(loras)}) and stripping lora tags for TEXT output.') - elif opt_model != None and opt_clip != None: - prompt, loras = get_and_strip_loras(prompt) - if len(loras): - for lora in loras: - opt_model, opt_clip = LoraLoader().load_lora(opt_model, opt_clip, lora['lora'], lora['strength'], lora['strength']) - log_node_success(NODE_NAME, f'Loaded "{lora["lora"]}" from prompt') - log_node_info(NODE_NAME, f'{len(loras)} Loras processed; stripping tags for TEXT output.') - elif ' 1 and len(match[1]) else 1.0) + if strength == 0 and not silent: + log_node_info(log_node, f'Skipping "{tag_filename}" with strength of zero') + continue + + # Let's be flexible. If the lora filename in the tag doesn't have the extension or + # path prefix, let's still find and load it. + if tag_filename not in lora_paths: + found_tag_filename = None + for index, value in enumerate(lora_filenames_no_ext): + if value in tag_filename: + found_tag_filename = lora_paths[index] + break + if found_tag_filename: + if not silent: + log_node_info(log_node, f'Found "{found_tag_filename}" for "{tag_filename}" in prompt') + tag_filename = found_tag_filename + else: + if not silent: + log_node_warn(log_node, f'Lora "{tag_filename}" not found, skipping.') + continue + + loras.append({'lora': tag_filename, 'strength': strength}) + + return (re.sub(pattern, '', prompt), loras) diff --git a/py/sdxl_config.py b/py/sdxl_config.py new file mode 100644 index 0000000..480fbd7 --- /dev/null +++ b/py/sdxl_config.py @@ -0,0 +1,47 @@ +"""Some basic config stuff I use for SDXL.""" + +from .constants import get_category, get_name +from nodes import MAX_RESOLUTION +import comfy.samplers + + +class RgthreeSDXLConfig: + """Some basic config stuff I use for SDXL.""" + + NAME = get_name('SDXL Config') + CATEGORY = get_category() + + @classmethod + def INPUT_TYPES(cls): # pylint: disable = invalid-name, missing-function-docstring + return { + "required": { + "steps_total": ("INT", { + "default": 30, + "min": 1, + "max": MAX_RESOLUTION + }), + "refiner_step": ("INT", { + "default": 24, + "min": 1, + "max": MAX_RESOLUTION + }), + "sampler_name": (comfy.samplers.KSampler.SAMPLERS,), + "scheduler": (comfy.samplers.KSampler.SCHEDULERS,), + #"refiner_ascore_pos": ("FLOAT", {"default": 6.0, "min": 0.0, "max": 1000.0, "step": 0.01}), + #"refiner_ascore_neg": ("FLOAT", {"default": 6.0, "min": 0.0, "max": 1000.0, "step": 0.01}), + }, + } + + RETURN_TYPES = ("INT", "INT", comfy.samplers.KSampler.SAMPLERS, + comfy.samplers.KSampler.SCHEDULERS) + RETURN_NAMES = ("STEPS", "REFINER_STEP", "SAMPLER", "SCHEDULER") + FUNCTION = "main" + + def main(self, steps_total, refiner_step, sampler_name, scheduler): + """main""" + return ( + steps_total, + refiner_step, + sampler_name, + scheduler, + ) diff --git a/py/sdxl_empty_latent_image.py b/py/sdxl_empty_latent_image.py index abf41a9..c367aaa 100644 --- a/py/sdxl_empty_latent_image.py +++ b/py/sdxl_empty_latent_image.py @@ -1,49 +1,63 @@ from nodes import EmptyLatentImage from .constants import get_category, get_name + class RgthreeSDXLEmptyLatentImage: - NAME = get_name('SDXL Empty Latent Image') - CATEGORY = get_category() + NAME = get_name('SDXL Empty Latent Image') + CATEGORY = get_category() - @classmethod - def INPUT_TYPES(cls): - return { - "required": { - "dimensions" : ([ - # 'Custom', - '1536 x 640 (landscape)', - '1344 x 768 (landscape)', - '1216 x 832 (landscape)', - '1152 x 896 (landscape)', - '1024 x 1024 (square)', - ' 896 x 1152 (portrait)', - ' 832 x 1216 (portrait)', - ' 768 x 1344 (portrait)', - ' 640 x 1536 (portrait)', - ], {"default": '1024 x 1024 (square)'}), - "clip_scale": ("FLOAT", {"default": 2.0, "min": 1.0, "max": 10.0, "step": .5}), - "batch_size": ("INT", {"default": 1, "min": 1, "max": 64}), - }, - "optional": { - # "custom_width": ("INT", {"min": 1, "max": MAX_RESOLUTION, "step": 64}), - # "custom_height": ("INT", {"min": 1, "max": MAX_RESOLUTION, "step": 64}), - } - } + @classmethod + def INPUT_TYPES(cls): # pylint: disable = invalid-name, missing-function-docstring + return { + "required": { + "dimensions": ( + [ + # 'Custom', + '1536 x 640 (landscape)', + '1344 x 768 (landscape)', + '1216 x 832 (landscape)', + '1152 x 896 (landscape)', + '1024 x 1024 (square)', + ' 896 x 1152 (portrait)', + ' 832 x 1216 (portrait)', + ' 768 x 1344 (portrait)', + ' 640 x 1536 (portrait)', + ], + { + "default": '1024 x 1024 (square)' + }), + "clip_scale": ("FLOAT", { + "default": 2.0, + "min": 1.0, + "max": 10.0, + "step": .5 + }), + "batch_size": ("INT", { + "default": 1, + "min": 1, + "max": 64 + }), + }, + # "optional": { + # "custom_width": ("INT", {"min": 1, "max": MAX_RESOLUTION, "step": 64}), + # "custom_height": ("INT", {"min": 1, "max": MAX_RESOLUTION, "step": 64}), + # } + } - RETURN_TYPES = ("LATENT", "INT", "INT") - RETURN_NAMES = ("LATENT", "CLIP_WIDTH", "CLIP_HEIGHT") - FUNCTION = "generate" + RETURN_TYPES = ("LATENT", "INT", "INT") + RETURN_NAMES = ("LATENT", "CLIP_WIDTH", "CLIP_HEIGHT") + FUNCTION = "generate" - # def generate(self, dimensions, clip_scale, batch_size, custom_width=1024, custom_height=1024): - def generate(self, dimensions, clip_scale, batch_size): - # if dimensions == 'Custom': - # width = custom_width - # height = custom_height - # else: - if True: - result = [x.strip() for x in dimensions.split('x')] - width = int(result[0]) - height = int(result[1].split(' ')[0]) - latent = EmptyLatentImage().generate(width, height, batch_size)[0] - return (latent, int(width * clip_scale), int(height * clip_scale),) \ No newline at end of file + def generate(self, dimensions, clip_scale, batch_size): + """Generates the latent and exposes the clip_width and clip_height""" + if True: + result = [x.strip() for x in dimensions.split('x')] + width = int(result[0]) + height = int(result[1].split(' ')[0]) + latent = EmptyLatentImage().generate(width, height, batch_size)[0] + return ( + latent, + int(width * clip_scale), + int(height * clip_scale), + ) diff --git a/py/sdxl_power_prompt_postive.py b/py/sdxl_power_prompt_postive.py new file mode 100644 index 0000000..4a963aa --- /dev/null +++ b/py/sdxl_power_prompt_postive.py @@ -0,0 +1,143 @@ +import os +import re +from nodes import MAX_RESOLUTION +from comfy_extras.nodes_clip_sdxl import CLIPTextEncodeSDXL, CLIPTextEncodeSDXLRefiner + +from .log import log_node_warn, log_node_info, log_node_success +from .constants import get_category, get_name +from .power_prompt_utils import get_and_strip_loras +from nodes import LoraLoader, CLIPTextEncode +import folder_paths + +NODE_NAME = get_name('SDXL Power Prompt - Positive') + + +class RgthreeSDXLPowerPromptPositive: + """The Power Prompt for positive conditioning.""" + + NAME = NODE_NAME + CATEGORY = get_category() + + @classmethod + def INPUT_TYPES(cls): # pylint: disable = invalid-name, missing-function-docstring + SAVED_PROMPTS_FILES = folder_paths.get_filename_list('saved_prompts') + SAVED_PROMPTS_CONTENT = [] + for filename in SAVED_PROMPTS_FILES: + with open(folder_paths.get_full_path('saved_prompts', filename), 'r') as f: + SAVED_PROMPTS_CONTENT.append(f.read()) + return { + 'required': { + 'prompt_g': ('STRING', { + 'multiline': True + }), + 'prompt_l': ('STRING', { + 'multiline': True + }), + }, + 'optional': { + "opt_model": ("MODEL",), + "opt_clip": ("CLIP",), + "opt_clip_width": ("INT", { + "forceInput": True, + "default": 1024.0, + "min": 0, + "max": MAX_RESOLUTION + }), + "opt_clip_height": ("INT", { + "forceInput": True, + "default": 1024.0, + "min": 0, + "max": MAX_RESOLUTION + }), + 'insert_lora': (['CHOOSE', 'DISABLE LORAS'] + + [os.path.splitext(x)[0] for x in folder_paths.get_filename_list('loras')],), + 'insert_embedding': ([ + 'CHOOSE', + ] + [os.path.splitext(x)[0] for x in folder_paths.get_filename_list('embeddings')],), + 'insert_saved': ([ + 'CHOOSE', + ] + SAVED_PROMPTS_FILES,), + # We'll hide these in the UI for now. + "target_width": ("INT", { + "default": -1, + "min": -1, + "max": MAX_RESOLUTION + }), + "target_height": ("INT", { + "default": -1, + "min": -1, + "max": MAX_RESOLUTION + }), + "crop_width": ("INT", { + "default": -1, + "min": -1, + "max": MAX_RESOLUTION + }), + "crop_height": ("INT", { + "default": -1, + "min": -1, + "max": MAX_RESOLUTION + }), + }, + 'hidden': { + 'values_insert_saved': (['CHOOSE'] + SAVED_PROMPTS_CONTENT,), + } + } + + RETURN_TYPES = ('CONDITIONING', 'MODEL', 'CLIP', 'STRING', 'STRING') + RETURN_NAMES = ('CONDITIONING', 'MODEL', 'CLIP', 'TEXT_G', 'TEXT_L') + FUNCTION = 'main' + + def main(self, + prompt_g, + prompt_l, + opt_model=None, + opt_clip=None, + opt_clip_width=None, + opt_clip_height=None, + insert_lora=None, + insert_embedding=None, + insert_saved=None, + target_width=-1, + target_height=-1, + crop_width=-1, + crop_height=-1, + values_insert_saved=None): + if insert_lora == 'DISABLE LORAS': + prompt_g, loras_g = get_and_strip_loras(prompt_g, True) + prompt_l, loras_l = get_and_strip_loras(prompt_l, True) + loras = loras_g + loras_l + log_node_info( + NODE_NAME, + f'Disabling all found loras ({len(loras)}) and stripping lora tags for TEXT output.') + elif opt_model != None and opt_clip != None: + prompt_g, loras_g = get_and_strip_loras(prompt_g) + prompt_l, loras_l = get_and_strip_loras(prompt_l) + loras = loras_g + loras_l + if len(loras): + for lora in loras: + opt_model, opt_clip = LoraLoader().load_lora(opt_model, opt_clip, lora['lora'], + lora['strength'], lora['strength']) + log_node_success(NODE_NAME, f'Loaded "{lora["lora"]}" from prompt') + log_node_info(NODE_NAME, f'{len(loras)} Loras processed; stripping tags for TEXT output.') + elif ' 0 else opt_clip_width + target_height = target_height if target_height and target_height > 0 else opt_clip_height + crop_width = crop_width if crop_width and crop_width > 0 else 0 + crop_height = crop_height if crop_height and crop_height > 0 else 0 + if opt_clip: + conditioning_base = CLIPTextEncodeSDXL().encode(opt_clip, opt_clip_width, opt_clip_height, + crop_width, crop_height, target_width, + target_height, prompt_g, prompt_l)[0] + + return (conditioning_base, opt_model, opt_clip, prompt_g, prompt_l) diff --git a/py/sdxl_power_prompt_simple.py b/py/sdxl_power_prompt_simple.py new file mode 100644 index 0000000..0322123 --- /dev/null +++ b/py/sdxl_power_prompt_simple.py @@ -0,0 +1,113 @@ +"""A simpler SDXL Power Prompt that doesn't load Loras, like for negative.""" +import os +import re +import folder_paths +from nodes import MAX_RESOLUTION, LoraLoader +from comfy_extras.nodes_clip_sdxl import CLIPTextEncodeSDXL + +from .log import log_node_warn, log_node_info, log_node_success + +from .constants import get_category, get_name + +NODE_NAME = get_name('SDXL Power Prompt - Simple / Negative') + + +class RgthreeSDXLPowerPromptSimple: + """A simpler SDXL Power Prompt that doesn't handle Loras.""" + + NAME = NODE_NAME + CATEGORY = get_category() + + @classmethod + def INPUT_TYPES(cls): # pylint: disable = invalid-name, missing-function-docstring + saved_prompts_files = folder_paths.get_filename_list('saved_prompts') + saved_promptes_content = [] + for fname in saved_prompts_files: + with open(folder_paths.get_full_path('saved_prompts', fname), 'r', encoding="utf-8") as file: + saved_promptes_content.append(file.read()) + + return { + 'required': { + 'prompt_g': ('STRING', { + 'multiline': True + }), + 'prompt_l': ('STRING', { + 'multiline': True + }), + }, + 'optional': { + "opt_clip": ("CLIP",), + "opt_clip_width": ("INT", { + "forceInput": True, + "default": 1024.0, + "min": 0, + "max": MAX_RESOLUTION + }), + "opt_clip_height": ("INT", { + "forceInput": True, + "default": 1024.0, + "min": 0, + "max": MAX_RESOLUTION + }), + 'insert_embedding': ([ + 'CHOOSE', + ] + [os.path.splitext(x)[0] for x in folder_paths.get_filename_list('embeddings')],), + 'insert_saved': ([ + 'CHOOSE', + ] + saved_prompts_files,), + # We'll hide these in the UI for now. + "target_width": ("INT", { + "default": -1, + "min": -1, + "max": MAX_RESOLUTION + }), + "target_height": ("INT", { + "default": -1, + "min": -1, + "max": MAX_RESOLUTION + }), + "crop_width": ("INT", { + "default": -1, + "min": -1, + "max": MAX_RESOLUTION + }), + "crop_height": ("INT", { + "default": -1, + "min": -1, + "max": MAX_RESOLUTION + }), + }, + 'hidden': { + 'values_insert_saved': (['CHOOSE'] + saved_promptes_content,), + } + } + + RETURN_TYPES = ('CONDITIONING', 'STRING', 'STRING') + RETURN_NAMES = ('CONDITIONING', 'TEXT_G', 'TEXT_L') + FUNCTION = 'main' + + def main(self, + prompt_g, + prompt_l, + opt_clip=None, + opt_clip_width=None, + opt_clip_height=None, + insert_embedding=None, + insert_saved=None, + target_width=-1, + target_height=-1, + crop_width=-1, + crop_height=-1, + values_insert_saved=None): + conditioning_base = None + if opt_clip_width and opt_clip_height: + target_width = target_width if target_width and target_width > 0 else opt_clip_width + target_height = target_height if target_height and target_height > 0 else opt_clip_height + crop_width = crop_width if crop_width and crop_width > 0 else 0 + crop_height = crop_height if crop_height and crop_height > 0 else 0 + if opt_clip: + conditioning_base = CLIPTextEncodeSDXL().encode(opt_clip, opt_clip_width, opt_clip_height, + crop_width, crop_height, target_width, + target_height, prompt_g, prompt_l)[0] + + return (conditioning_base, prompt_g, prompt_l)