New SDXL Power Prompt, Image Inset, Config, and more.

This commit is contained in:
rgthree
2023-09-11 21:56:03 -04:00
parent b8ec1d8556
commit 3cb4df567d
8 changed files with 590 additions and 175 deletions
+36
View File
@@ -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,)}}
+75 -46
View File
@@ -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,)
+77 -88
View File
@@ -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='<lora:([^:>]*?)(?::(-?\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 '<lora:' in prompt:
_prompt_stripped, loras = get_and_strip_loras(prompt, True)
if len(loras):
log_node_warn(NODE_NAME, f'Found {len(loras)} lora tags in prompt but model & clip were not supplied!')
log_node_info(NODE_NAME, f'Loras not processed, keeping for TEXT output.')
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, log_node=NODE_NAME, silent=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, log_node=NODE_NAME)
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 '<lora:' in prompt:
_prompt_stripped, loras = get_and_strip_loras(prompt, log_node=NODE_NAME, silent=True)
if len(loras):
log_node_warn(
NODE_NAME, f'Found {len(loras)} lora tags in prompt but model & clip were not supplied!')
log_node_info(NODE_NAME, 'Loras not processed, keeping for TEXT output.')
conditioning=None
if opt_clip != None:
conditioning = CLIPTextEncode().encode(opt_clip, prompt)[0]
return (conditioning, opt_model, opt_clip, prompt)
conditioning = None
if opt_clip != None:
conditioning = CLIPTextEncode().encode(opt_clip, prompt)[0]
return (conditioning, opt_model, opt_clip, prompt)
+44
View File
@@ -0,0 +1,44 @@
"""Utilities for Power Prompt nodes."""
import re
import os
import folder_paths
from .log import log_node_warn, log_node_info
def get_and_strip_loras(prompt, silent=False, log_node="Power Prompt"):
"""Collects and strips lora tags from a prompt."""
pattern = '<lora:([^:>]*?)(?::(-?\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(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)
+47
View File
@@ -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,
)
+55 -41
View File
@@ -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),)
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),
)
+143
View File
@@ -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 '<lora:' in prompt_g or '<lora:' in prompt_l:
_prompt_stripped_g, loras_g = get_and_strip_loras(prompt_g, True)
_prompt_stripped_l, loras_l = get_and_strip_loras(prompt_l, True)
loras = loras_g + loras_l
if len(loras):
log_node_warn(
NODE_NAME, f'Found {len(loras)} lora tags in prompt but model & clip were not supplied!')
log_node_info(NODE_NAME, 'Loras not processed, keeping for TEXT output.')
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, opt_model, opt_clip, prompt_g, prompt_l)
+113
View File
@@ -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)