File size: 17,035 Bytes
ca2a3d8 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 |
from . import SwarmLoadImageB64
import folder_paths
from nodes import CheckpointLoaderSimple, LoadImage
from comfy_extras.nodes_video import LoadVideo
from comfy_api.input_impl import VideoFromFile
import os, base64, io
try:
from comfy_extras.nodes_audio import LoadAudio
from comfy_extras.nodes_audio import load as raw_audio_load
except ImportError:
print("Error: Nodes_Audio failed to import")
INT_MAX = 0xffffffffffffffff
INT_MIN = -INT_MAX
class SwarmInputGroup:
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"title": ("STRING", {"default": "My Group", "tooltip": "The title of the group."}),
"open_by_default": ("BOOLEAN", {"default": True, "tooltip": "Whether the group should be open by default."}),
"description": ("STRING", {"default": "", "multiline": True, "tooltip": "A description of the group that shows up when you click the '?' button."}),
"order_priority": ("FLOAT", {"default": 0, "min": -1024, "max": 1024, "step": 0.5, "round": 0.0000001, "tooltip": "The order priority of the group. Higher values go further down in the list of groups."}),
"is_advanced": ("BOOLEAN", {"default": False, "tooltip": "If true, the group will only be visible when 'Display Advanced' is clicked."}),
"can_shrink": ("BOOLEAN", {"default": True, "tooltip": "If true, the group can be collapsed by the user. If false, will be forced to remain open."}),
},
}
CATEGORY = "SwarmUI/inputs"
RETURN_TYPES = ("GROUP",)
FUNCTION = "do_input"
DESCRIPTION = "SwarmInput nodes let you define custom input controls in Swarm-Comfy Workflows. Group defines a parameter groupging - link this to other nodes to create a collapsible group, all nodes this links to will be inside the group."
def do_input(self, **kwargs):
return (None, )
STANDARD_REQ_INPUTS = {
"description": ("STRING", {"default": "", "multiline": True, "tooltip": "A description of the input that shows up when you click the '?' button."}),
"order_priority": ("FLOAT", {"default": 0, "min": -1024, "max": 1024, "step": 0.5, "round": 0.0000001, "tooltip": "The order priority of the input. Higher values go further down in the list of inputs. This only applies within the group this node is part of."}),
"is_advanced": ("BOOLEAN", {"default": False, "tooltip": "If true, the input will only be visible when 'Display Advanced' is clicked."}),
"raw_id": ("STRING", {"default": "", "tooltip": "The raw ID of the input. This can be used to customize the input for API usage, or to make use of default SwarmUI parameters. Most of the time, you don't need to touch this. By default this will autogenerate a unique ID based on the title value."}),
}
STANDARD_OTHER_INPUTS = {
"optional": {
"group": ("GROUP", )
}
}
class SwarmInputInteger:
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"title": ("STRING", {"default": "My Integer", "tooltip": "The name of the input."}),
"value": ("INT", {"default": 0, "min": INT_MIN, "max": INT_MAX, "step": 1, "tooltip": "The default value of the input."}),
"step": ("INT", {"default": 1, "min": INT_MIN, "max": INT_MAX, "step": 1, "tooltip": "The step size of the input. That is, how much the value changes when you click the up/down arrows or move the slider."}),
"min": ("INT", {"default": 0, "min": INT_MIN, "max": INT_MAX, "step": 1, "tooltip": "The minimum value of the input."}),
"max": ("INT", {"default": 100, "min": INT_MIN, "max": INT_MAX, "step": 1, "tooltip": "The maximum value of the input."}),
"view_max": ("INT", {"default": 100, "min": INT_MIN, "max": INT_MAX, "step": 1, "tooltip": "The maximum value of the input that is displayed in the UI when using a slider. This is useful if you want to allow a higher range of values, but don't want to clutter the UI with a huge slider."}),
"view_type": (["big", "small", "seed", "slider", "pot_slider"],{"tooltip": "The type of input control to use. 'big' is a large text input, 'small' is a small text input, 'seed' is a text input with seed-specific controls, 'slider' is a slider, and 'pot_slider' is a Power-Of-Two scaled slider - this is useful for large inputs like resolutions to allow a more natural feeling selection range."}),
} | STANDARD_REQ_INPUTS,
} | STANDARD_OTHER_INPUTS
CATEGORY = "SwarmUI/inputs"
RETURN_TYPES = ("INT",)
FUNCTION = "do_input"
DESCRIPTION = "SwarmInput nodes let you define custom input controls in Swarm-Comfy Workflows. Integer lets you input a whole number without a decimal point."
def do_input(self, value, **kwargs):
return (value, )
class SwarmInputFloat:
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"title": ("STRING", {"default": "My Floating-Point Number", "tooltip": "The name of the input."}),
"value": ("FLOAT", {"default": 0, "min": INT_MIN, "max": INT_MAX, "step": 0.01, "round": 0.0000001, "tooltip": "The default value of the input."}),
"step": ("FLOAT", {"default": 0.1, "min": INT_MIN, "max": INT_MAX, "step": 0.01, "round": 0.0000001, "tooltip": "The step size of the input. That is, how much the value changes when you click the up/down arrows or move the slider."}),
"min": ("FLOAT", {"default": 0, "min": INT_MIN, "max": INT_MAX, "step": 0.01, "round": 0.0000001, "tooltip": "The minimum value of the input."}),
"max": ("FLOAT", {"default": 100, "min": INT_MIN, "max": INT_MAX, "step": 0.01, "round": 0.0000001, "tooltip": "The maximum value of the input."}),
"view_max": ("FLOAT", {"default": 100, "min": INT_MIN, "max": INT_MAX, "step": 0.01, "round": 0.0000001, "tooltip": "The maximum value of the input that is displayed in the UI when using a slider. This is useful if you want to allow a higher range of values, but don't want to clutter the UI with a huge slider."}),
"view_type": (["big", "small", "slider", "pot_slider"], {"tooltip": "The type of input control to use. 'big' is a large text input, 'small' is a small text input, 'slider' is a slider, and 'pot_slider' is a Power-Of-Two scaled slider - this is useful for large inputs like resolutions to allow a more natural feeling selection range."}),
} | STANDARD_REQ_INPUTS,
} | STANDARD_OTHER_INPUTS
CATEGORY = "SwarmUI/inputs"
RETURN_TYPES = ("FLOAT",)
FUNCTION = "do_input"
DESCRIPTION = "SwarmInput nodes let you define custom input controls in Swarm-Comfy Workflows. Float lets you input a number with a decimal point."
def do_input(self, value, **kwargs):
return (value, )
class SwarmInputText:
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"title": ("STRING", {"default": "My Text", "tooltip": "The name of the input."}),
"value": ("STRING", {"default": "", "multiline": True, "tooltip": "The default value of the input."}),
"view_type": (["normal", "prompt", "big"], {"tooltip": "How to format this text input. 'normal' is a simple single line text input, 'prompt' is a prompt-like text input that has multiple lines and other prompting-specific features, 'big' is an extra large multiline text box."}),
} | STANDARD_REQ_INPUTS,
} | STANDARD_OTHER_INPUTS
CATEGORY = "SwarmUI/inputs"
RETURN_TYPES = ("STRING",)
FUNCTION = "do_input"
DESCRIPTION = "SwarmInput nodes let you define custom input controls in Swarm-Comfy Workflows. Text lets you input a string of text. This can be simple text inputs, or prompt-like text inputs."
def do_input(self, value, **kwargs):
return (value, )
class SwarmInputModelName:
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"title": ("STRING", {"default": "My Model Name Input", "tooltip": "The name of the input."}),
"value": ("STRING", {"default": "", "multiline": False, "tooltip": "The default value of the input."}),
"subtype": (["Stable-Diffusion", "VAE", "LoRA", "Embedding", "ControlNet", "ClipVision"], {"tooltip": "The model subtype to select from."}),
} | STANDARD_REQ_INPUTS,
} | STANDARD_OTHER_INPUTS
CATEGORY = "SwarmUI/inputs"
RETURN_TYPES = ("",)
FUNCTION = "do_input"
DESCRIPTION = "SwarmInput nodes let you define custom input controls in Swarm-Comfy Workflows. Model Name lets you have a dropdown select for models of a given model sub-type."
def do_input(self, value, **kwargs):
return (value, )
class SwarmInputCheckpoint:
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"title": ("STRING", {"default": "My Checkpoint Model Name Input", "tooltip": "The name of the input."}),
"value": (folder_paths.get_filename_list("checkpoints"), {"tooltip": "The default value of the input."}),
} | STANDARD_REQ_INPUTS,
} | STANDARD_OTHER_INPUTS
CATEGORY = "SwarmUI/inputs"
RETURN_TYPES = ("MODEL", "CLIP", "VAE")
FUNCTION = "do_input"
DESCRIPTION = "SwarmInput nodes let you define custom input controls in Swarm-Comfy Workflows. Checkpoint lets you have a dropdown select for checkpoint models. Acts like the Checkpoint Loader node."
def do_input(self, value, **kwargs):
return CheckpointLoaderSimple().load_checkpoint(value)
class SwarmInputDropdown:
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"title": ("STRING", {"default": "My Dropdown", "tooltip": "The name of the input."}),
"value": ("STRING", {"default": "", "multiline": False, "tooltip": "The default value of the input."}),
"values": ("STRING", {"default": "one, two, three", "multiline": True, "tooltip": "A comma-separated list of values to choose from. If you leave this blank, the dropdown will automatically load the value list from the connected node."}),
} | STANDARD_REQ_INPUTS,
} | STANDARD_OTHER_INPUTS
CATEGORY = "SwarmUI/inputs"
RETURN_TYPES = ("STRING", "",)
FUNCTION = "do_input"
DESCRIPTION = "SwarmInput nodes let you define custom input controls in Swarm-Comfy Workflows. Dropdown lets you have a dropdown select for a list of values. You can leave the values list empty and attach the blank output to a real dropdown in another node to have it automatically load the value list from that connected node."
def do_input(self, value, **kwargs):
return (value, value, )
class SwarmInputBoolean:
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"title": ("STRING", {"default": "My Boolean", "tooltip": "The name of the input."}),
"value": ("BOOLEAN", {"default": False, "tooltip": "The default value of the input."}),
} | STANDARD_REQ_INPUTS,
} | STANDARD_OTHER_INPUTS
CATEGORY = "SwarmUI/inputs"
RETURN_TYPES = ("BOOLEAN",)
FUNCTION = "do_input"
DESCRIPTION = "SwarmInput nodes let you define custom input controls in Swarm-Comfy Workflows. Boolean lets you have a checkbox for a true/false value."
def do_input(self, value, **kwargs):
return (value, )
class SwarmInputImage:
@classmethod
def INPUT_TYPES(s):
input_dir = folder_paths.get_input_directory()
files = [f for f in os.listdir(input_dir) if os.path.isfile(os.path.join(input_dir, f))]
files = folder_paths.filter_files_content_types(files, ["image"])
return {
"required": {
"title": ("STRING", {"default": "My Image", "tooltip": "The name of the input."}),
"value": ("STRING", {"default": "(Do Not Set Me)", "multiline": True, "tooltip": "Always leave this blank, the SwarmUI server will fill it for you."}),
"auto_resize": ("BOOLEAN", {"default": True, "tooltip": "If true, the image will be resized to match the current generation resolution. If false, the image will be kept at whatever size the user input it at."}),
} | STANDARD_REQ_INPUTS | {
"image": (sorted(files), {"image_upload": True}),
},
} | STANDARD_OTHER_INPUTS
CATEGORY = "SwarmUI/inputs"
RETURN_TYPES = ("IMAGE","MASK",)
FUNCTION = "do_input"
DESCRIPTION = "SwarmInput nodes let you define custom input controls in Swarm-Comfy Workflows. Image lets you input an image. Internally this node uses a Base64 string as input when value is set by SwarmUI server (Generate tab), otherwise use select Image (Comfy Workflow tab)."
def do_input(self, value=None, image=None, **kwargs):
if not value or value == "(Do Not Set Me)":
return LoadImage().load_image(image)
else:
return SwarmLoadImageB64.b64_to_img_and_mask(value)
class SwarmInputAudio:
@classmethod
def INPUT_TYPES(s):
input_dir = folder_paths.get_input_directory()
files = [f for f in os.listdir(input_dir) if os.path.isfile(os.path.join(input_dir, f))]
files = folder_paths.filter_files_content_types(files, ["audio"])
return {
"required": {
"title": ("STRING", {"default": "My Audio", "tooltip": "The name of the input."}),
"value": ("STRING", {"default": "(Do Not Set Me)", "multiline": True, "tooltip": "Always leave this blank, the SwarmUI server will fill it for you."}),
} | STANDARD_REQ_INPUTS | {
# TODO: This explodes the comfy frontend for some reason
#"audio": (sorted(files), {"audio_upload": True}),
},
} | STANDARD_OTHER_INPUTS
CATEGORY = "SwarmUI/inputs"
RETURN_TYPES = ("AUDIO",)
FUNCTION = "do_input"
DESCRIPTION = "SwarmInput nodes let you define custom input controls in Swarm-Comfy Workflows. Audio lets you input an audio file. Internally this node uses a Base64 string as input when value is set by SwarmUI server (Generate tab), otherwise use select Audio (Comfy Workflow tab)."
def do_input(self, value=None, audio=None, **kwargs):
if not value or value == "(Do Not Set Me)":
return LoadAudio().load_audio(audio)
else:
audio_data = base64.b64decode(value)
audio_bytes = io.BytesIO(audio_data)
waveform, sample_rate = raw_audio_load(audio_bytes)
audio = {"waveform": waveform.unsqueeze(0), "sample_rate": sample_rate}
return (audio, )
class SwarmInputVideo:
@classmethod
def INPUT_TYPES(s):
input_dir = folder_paths.get_input_directory()
files = [f for f in os.listdir(input_dir) if os.path.isfile(os.path.join(input_dir, f))]
files = folder_paths.filter_files_content_types(files, ["video"])
return {
"required": {
"title": ("STRING", {"default": "My Video", "tooltip": "The name of the input."}),
"value": ("STRING", {"default": "(Do Not Set Me)", "multiline": True, "tooltip": "Always leave this blank, the SwarmUI server will fill it for you."}),
} | STANDARD_REQ_INPUTS | {
"video": (sorted(files), {"video_upload": True}),
},
} | STANDARD_OTHER_INPUTS
CATEGORY = "SwarmUI/inputs"
RETURN_TYPES = ("VIDEO",)
FUNCTION = "do_input"
DESCRIPTION = "SwarmInput nodes let you define custom input controls in Swarm-Comfy Workflows. Video lets you input a video file. Internally this node uses a Base64 string as input when value is set by SwarmUI server (Generate tab), otherwise use select Video (Comfy Workflow tab)."
def do_input(self, value=None, video=None, **kwargs):
if not value or value == "(Do Not Set Me)":
return LoadVideo.execute(video)
else:
video_data = base64.b64decode(value)
video_bytes = io.BytesIO(video_data)
return (VideoFromFile(video_bytes), )
NODE_CLASS_MAPPINGS = {
"SwarmInputGroup": SwarmInputGroup,
"SwarmInputInteger": SwarmInputInteger,
"SwarmInputFloat": SwarmInputFloat,
"SwarmInputText": SwarmInputText,
"SwarmInputModelName": SwarmInputModelName,
"SwarmInputCheckpoint": SwarmInputCheckpoint,
"SwarmInputDropdown": SwarmInputDropdown,
"SwarmInputBoolean": SwarmInputBoolean,
"SwarmInputImage": SwarmInputImage,
"SwarmInputAudio": SwarmInputAudio,
"SwarmInputVideo": SwarmInputVideo,
}
|