diff --git a/nodes.py b/nodes.py index 6fb7f0175..421849c64 100644 --- a/nodes.py +++ b/nodes.py @@ -40,7 +40,7 @@ class CLIPTextEncode: RETURN_TYPES = ("CONDITIONING",) FUNCTION = "encode" - CATEGORY = "conditioning" + CATEGORY = "Conditioning" def encode(self, clip, text): return ([[clip.encode(text), {}]], ) @@ -52,7 +52,7 @@ class ConditioningCombine: RETURN_TYPES = ("CONDITIONING",) FUNCTION = "combine" - CATEGORY = "conditioning" + CATEGORY = "Conditioning" def combine(self, conditioning_1, conditioning_2): return (conditioning_1 + conditioning_2, ) @@ -70,7 +70,7 @@ class ConditioningSetArea: RETURN_TYPES = ("CONDITIONING",) FUNCTION = "append" - CATEGORY = "conditioning" + CATEGORY = "Conditioning" def append(self, conditioning, width, height, x, y, strength, min_sigma=0.0, max_sigma=99.0): c = [] @@ -93,7 +93,7 @@ class VAEDecode: RETURN_TYPES = ("IMAGE",) FUNCTION = "decode" - CATEGORY = "latent" + CATEGORY = "Latent" def decode(self, vae, samples): return (vae.decode(samples["samples"]), ) @@ -123,7 +123,7 @@ class VAEEncode: RETURN_TYPES = ("LATENT",) FUNCTION = "encode" - CATEGORY = "latent" + CATEGORY = "Latent" def encode(self, vae, pixels): x = (pixels.shape[1] // 64) * 64 @@ -165,7 +165,7 @@ class VAEEncodeForInpaint: RETURN_TYPES = ("LATENT",) FUNCTION = "encode" - CATEGORY = "latent/inpaint" + CATEGORY = "Latent/Inpaint" def encode(self, vae, pixels, mask): x = (pixels.shape[1] // 64) * 64 @@ -197,7 +197,7 @@ class CheckpointLoader: RETURN_TYPES = ("MODEL", "CLIP", "VAE") FUNCTION = "load_checkpoint" - CATEGORY = "loaders" + CATEGORY = "Loaders" def load_checkpoint(self, config_name, ckpt_name, output_vae=True, output_clip=True): config_path = folder_paths.get_full_path("configs", config_name) @@ -212,7 +212,7 @@ class CheckpointLoaderSimple: RETURN_TYPES = ("MODEL", "CLIP", "VAE") FUNCTION = "load_checkpoint" - CATEGORY = "loaders" + CATEGORY = "Loaders" def load_checkpoint(self, ckpt_name, output_vae=True, output_clip=True): ckpt_path = folder_paths.get_full_path("checkpoints", ckpt_name) @@ -228,7 +228,7 @@ class CLIPSetLastLayer: RETURN_TYPES = ("CLIP",) FUNCTION = "set_last_layer" - CATEGORY = "conditioning" + CATEGORY = "Conditioning" def set_last_layer(self, clip, stop_at_clip_layer): clip = clip.clone() @@ -247,7 +247,7 @@ class LoraLoader: RETURN_TYPES = ("MODEL", "CLIP") FUNCTION = "load_lora" - CATEGORY = "loaders" + CATEGORY = "Loaders" def load_lora(self, model, clip, lora_name, strength_model, strength_clip): lora_path = folder_paths.get_full_path("loras", lora_name) @@ -261,7 +261,7 @@ class VAELoader: RETURN_TYPES = ("VAE",) FUNCTION = "load_vae" - CATEGORY = "loaders" + CATEGORY = "Loaders" #TODO: scale factor? def load_vae(self, vae_name): @@ -277,7 +277,7 @@ class ControlNetLoader: RETURN_TYPES = ("CONTROL_NET",) FUNCTION = "load_controlnet" - CATEGORY = "loaders" + CATEGORY = "Loaders" def load_controlnet(self, control_net_name): controlnet_path = folder_paths.get_full_path("controlnet", control_net_name) @@ -293,7 +293,7 @@ class DiffControlNetLoader: RETURN_TYPES = ("CONTROL_NET",) FUNCTION = "load_controlnet" - CATEGORY = "loaders" + CATEGORY = "Loaders" def load_controlnet(self, model, control_net_name): controlnet_path = folder_paths.get_full_path("controlnet", control_net_name) @@ -312,7 +312,7 @@ class ControlNetApply: RETURN_TYPES = ("CONDITIONING",) FUNCTION = "apply_controlnet" - CATEGORY = "conditioning" + CATEGORY = "Conditioning" def apply_controlnet(self, conditioning, control_net, image, strength): c = [] @@ -335,7 +335,7 @@ class CLIPLoader: RETURN_TYPES = ("CLIP",) FUNCTION = "load_clip" - CATEGORY = "loaders" + CATEGORY = "Loaders" def load_clip(self, clip_name): clip_path = folder_paths.get_full_path("clip", clip_name) @@ -350,7 +350,7 @@ class CLIPVisionLoader: RETURN_TYPES = ("CLIP_VISION",) FUNCTION = "load_clip" - CATEGORY = "loaders" + CATEGORY = "Loaders" def load_clip(self, clip_name): clip_path = folder_paths.get_full_path("clip_vision", clip_name) @@ -366,7 +366,7 @@ class CLIPVisionEncode: RETURN_TYPES = ("CLIP_VISION_OUTPUT",) FUNCTION = "encode" - CATEGORY = "conditioning/style_model" + CATEGORY = "Conditioning/Style Model" def encode(self, clip_vision, image): output = clip_vision.encode_image(image) @@ -380,7 +380,7 @@ class StyleModelLoader: RETURN_TYPES = ("STYLE_MODEL",) FUNCTION = "load_style_model" - CATEGORY = "loaders" + CATEGORY = "Loaders" def load_style_model(self, style_model_name): style_model_path = folder_paths.get_full_path("style_models", style_model_name) @@ -398,7 +398,7 @@ class StyleModelApply: RETURN_TYPES = ("CONDITIONING",) FUNCTION = "apply_stylemodel" - CATEGORY = "conditioning/style_model" + CATEGORY = "Conditioning/Style Model" def apply_stylemodel(self, clip_vision_output, style_model, conditioning): cond = style_model.get_cond(clip_vision_output) @@ -420,7 +420,7 @@ class EmptyLatentImage: RETURN_TYPES = ("LATENT",) FUNCTION = "generate" - CATEGORY = "latent" + CATEGORY = "Latent" def generate(self, width, height, batch_size=1): latent = torch.zeros([batch_size, 4, height // 8, width // 8]) @@ -441,7 +441,7 @@ class LatentUpscale: RETURN_TYPES = ("LATENT",) FUNCTION = "upscale" - CATEGORY = "latent" + CATEGORY = "Latent" def upscale(self, samples, upscale_method, width, height, crop): s = samples.copy() @@ -457,7 +457,7 @@ class LatentRotate: RETURN_TYPES = ("LATENT",) FUNCTION = "rotate" - CATEGORY = "latent/transform" + CATEGORY = "Latent/Transform" def rotate(self, samples, rotation): s = samples.copy() @@ -481,7 +481,7 @@ class LatentFlip: RETURN_TYPES = ("LATENT",) FUNCTION = "flip" - CATEGORY = "latent/transform" + CATEGORY = "Latent/Transform" def flip(self, samples, flip_method): s = samples.copy() @@ -504,7 +504,7 @@ class LatentComposite: RETURN_TYPES = ("LATENT",) FUNCTION = "composite" - CATEGORY = "latent" + CATEGORY = "Latent" def composite(self, samples_to, samples_from, x, y, composite_method="normal", feather=0): x = x // 8 @@ -546,7 +546,7 @@ class LatentCrop: RETURN_TYPES = ("LATENT",) FUNCTION = "crop" - CATEGORY = "latent/transform" + CATEGORY = "Latent/Transform" def crop(self, samples, width, height, x, y): s = samples.copy() @@ -586,7 +586,7 @@ class SetLatentNoiseMask: RETURN_TYPES = ("LATENT",) FUNCTION = "set_mask" - CATEGORY = "latent/inpaint" + CATEGORY = "Latent/Inpaint" def set_mask(self, samples, mask): s = samples.copy() @@ -679,7 +679,7 @@ class KSampler: RETURN_TYPES = ("LATENT",) FUNCTION = "sample" - CATEGORY = "sampling" + CATEGORY = "Sampling" def sample(self, model, seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, denoise=1.0): return common_ksampler(model, seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, denoise=denoise) @@ -706,7 +706,7 @@ class KSamplerAdvanced: RETURN_TYPES = ("LATENT",) FUNCTION = "sample" - CATEGORY = "sampling" + CATEGORY = "Sampling" def sample(self, model, add_noise, noise_seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, start_at_step, end_at_step, return_with_leftover_noise, denoise=1.0): force_full_denoise = True @@ -735,7 +735,7 @@ class SaveImage: OUTPUT_NODE = True - CATEGORY = "image" + CATEGORY = "Image" def save_images(self, images, filename_prefix="ComfyUI", prompt=None, extra_pnginfo=None): def map_filename(filename): @@ -818,7 +818,7 @@ class LoadImage: {"image": (sorted(os.listdir(s.input_dir)), )}, } - CATEGORY = "image" + CATEGORY = "Image" RETURN_TYPES = ("IMAGE", "MASK") FUNCTION = "load_image" @@ -852,7 +852,7 @@ class LoadImageMask: "channel": (["alpha", "red", "green", "blue"], ),} } - CATEGORY = "image" + CATEGORY = "Image" RETURN_TYPES = ("MASK",) FUNCTION = "load_image" @@ -891,7 +891,7 @@ class ImageScale: RETURN_TYPES = ("IMAGE",) FUNCTION = "upscale" - CATEGORY = "image/upscaling" + CATEGORY = "Image/Upscaling" def upscale(self, image, upscale_method, width, height, crop): samples = image.movedim(-1,1) @@ -908,7 +908,7 @@ class ImageInvert: RETURN_TYPES = ("IMAGE",) FUNCTION = "invert" - CATEGORY = "image" + CATEGORY = "Image" def invert(self, image): s = 1.0 - image @@ -933,7 +933,7 @@ class ImagePadForOutpaint: RETURN_TYPES = ("IMAGE", "MASK") FUNCTION = "expand_image" - CATEGORY = "image" + CATEGORY = "Image" def expand_image(self, image, left, top, right, bottom, feathering): d1, d2, d3, d4 = image.size() @@ -979,43 +979,43 @@ class ImagePadForOutpaint: NODE_CLASS_MAPPINGS = { + "CLIP Loader": CLIPLoader, + "CLIP Set Last Layer": CLIPSetLastLayer, + "CLIP Text Encode": CLIPTextEncode, + "CLIP Vision Encode": CLIPVisionEncode, + "CLIP Vision Loader": CLIPVisionLoader, + "Checkpoint Loader": CheckpointLoader, + "Checkpoint Loader (Simple)": CheckpointLoaderSimple, + "Conditioning Combine": ConditioningCombine, + "Conditioning Set Area": ConditioningSetArea, + "ControlNet Apply": ControlNetApply, + "ControlNet Loader": ControlNetLoader, + "Diff ControlNet Loader": DiffControlNetLoader, + "Empty Latent Image": EmptyLatentImage, + "Image Invert": ImageInvert, + "Image Padding (Outpaint)": ImagePadForOutpaint, + "Image Scale": ImageScale, "KSampler": KSampler, - "CheckpointLoader": CheckpointLoader, - "CheckpointLoaderSimple": CheckpointLoaderSimple, - "CLIPTextEncode": CLIPTextEncode, - "CLIPSetLastLayer": CLIPSetLastLayer, - "VAEDecode": VAEDecode, - "VAEEncode": VAEEncode, - "VAEEncodeForInpaint": VAEEncodeForInpaint, - "VAELoader": VAELoader, - "EmptyLatentImage": EmptyLatentImage, - "LatentUpscale": LatentUpscale, - "SaveImage": SaveImage, - "PreviewImage": PreviewImage, - "LoadImage": LoadImage, - "LoadImageMask": LoadImageMask, - "ImageScale": ImageScale, - "ImageInvert": ImageInvert, - "ImagePadForOutpaint": ImagePadForOutpaint, - "ConditioningCombine": ConditioningCombine, - "ConditioningSetArea": ConditioningSetArea, - "KSamplerAdvanced": KSamplerAdvanced, - "SetLatentNoiseMask": SetLatentNoiseMask, - "LatentComposite": LatentComposite, - "LatentRotate": LatentRotate, - "LatentFlip": LatentFlip, - "LatentCrop": LatentCrop, - "LoraLoader": LoraLoader, - "CLIPLoader": CLIPLoader, - "CLIPVisionEncode": CLIPVisionEncode, - "StyleModelApply": StyleModelApply, - "ControlNetApply": ControlNetApply, - "ControlNetLoader": ControlNetLoader, - "DiffControlNetLoader": DiffControlNetLoader, - "StyleModelLoader": StyleModelLoader, - "CLIPVisionLoader": CLIPVisionLoader, - "VAEDecodeTiled": VAEDecodeTiled, - "VAEEncodeTiled": VAEEncodeTiled, + "KSampler (Advanced)": KSamplerAdvanced, + "Latent Composite": LatentComposite, + "Latent Crop": LatentCrop, + "Latent Flip": LatentFlip, + "Latent Rotate": LatentRotate, + "Latent Upscale": LatentUpscale, + "Load Image": LoadImage, + "Load Image Mask": LoadImageMask, + "Lora Loader": LoraLoader, + "Preview Image": PreviewImage, + "Save Image": SaveImage, + "Mask Latent Noise": SetLatentNoiseMask, + "Style Model Apply": StyleModelApply, + "Style Model Loader": StyleModelLoader, + "VAE Decode": VAEDecode, + "VAE Decode (Tiled)": VAEDecodeTiled, + "VAE Encode": VAEEncode, + "VAE Encode (Inpaint)": VAEEncodeForInpaint, + "VAE Encode (Tiled)": VAEEncodeTiled, + "VAE Loader": VAELoader, } def load_custom_node(module_path): @@ -1052,4 +1052,4 @@ def load_custom_nodes(): load_custom_nodes() -load_custom_node(os.path.join(os.path.join(os.path.dirname(os.path.realpath(__file__)), "comfy_extras"), "nodes_upscale_model.py")) \ No newline at end of file +load_custom_node(os.path.join(os.path.join(os.path.dirname(os.path.realpath(__file__)), "comfy_extras"), "nodes_upscale_model.py")) diff --git a/web/extensions/core/rerouteNode.js b/web/extensions/core/rerouteNode.js index 7188dfd26..db3b2afaa 100644 --- a/web/extensions/core/rerouteNode.js +++ b/web/extensions/core/rerouteNode.js @@ -189,6 +189,6 @@ app.registerExtension({ }) ); - RerouteNode.category = "utils"; + RerouteNode.category = "Utilities"; }, }); diff --git a/web/extensions/core/widgetInputs.js b/web/extensions/core/widgetInputs.js index ff9227d28..36961c879 100644 --- a/web/extensions/core/widgetInputs.js +++ b/web/extensions/core/widgetInputs.js @@ -357,6 +357,6 @@ app.registerExtension({ title: "Primitive", }) ); - PrimitiveNode.category = "utils"; + PrimitiveNode.category = "Utilities"; }, }); diff --git a/web/scripts/ui.js b/web/scripts/ui.js index c79caaa9b..c953e1125 100644 --- a/web/scripts/ui.js +++ b/web/scripts/ui.js @@ -313,7 +313,7 @@ export class ComfyUI { this.menuContainer = $el("div.comfy-menu", { parent: document.body }, [ $el("div", { style: { overflow: "hidden", position: "relative", width: "100%" } }, [ $el("span.drag-handle"), - $el("span", { $: (q) => (this.queueSize = q) }), + $el("span", { className: "comfy-queue-size", $: (q) => (this.queueSize = q) }), $el("button.comfy-settings-btn", { textContent: "⚙️", onclick: () => this.settings.show() }), ]), $el("button.comfy-queue-btn", { textContent: "Queue Prompt", onclick: () => app.queuePrompt(0, this.batchCount) }), @@ -347,10 +347,11 @@ export class ComfyUI { ]), ]), $el("div.comfy-menu-btns", [ - $el("button", { textContent: "Queue Front", onclick: () => app.queuePrompt(-1, this.batchCount) }), + $el("button", { textContent: "Queue Front", className: "comfy-queue-front-btn", onclick: () => app.queuePrompt(-1, this.batchCount) }), $el("button", { $: (b) => (this.queue.button = b), textContent: "View Queue", + className: "comfy-view-queue-btn", onclick: () => { this.history.hide(); this.queue.toggle(); @@ -359,6 +360,7 @@ export class ComfyUI { $el("button", { $: (b) => (this.history.button = b), textContent: "View History", + className: "comfy-history-btn", onclick: () => { this.queue.hide(); this.history.toggle(); @@ -369,6 +371,7 @@ export class ComfyUI { this.history.element, $el("button", { textContent: "Save", + className: "comfy-save-btn", onclick: () => { const json = JSON.stringify(app.graph.serialize(), null, 2); // convert the data to a JSON string const blob = new Blob([json], { type: "application/json" }); @@ -386,10 +389,10 @@ export class ComfyUI { }, 0); }, }), - $el("button", { textContent: "Load", onclick: () => fileInput.click() }), - $el("button", { textContent: "Refresh", onclick: () => app.refreshComboInNodes() }), - $el("button", { textContent: "Clear", onclick: () => app.graph.clear() }), - $el("button", { textContent: "Load Default", onclick: () => app.loadGraphData() }), + $el("button", { textContent: "Load", className: "comfy-load-btn", onclick: () => fileInput.click() }), + $el("button", { textContent: "Clear", className: "comfy-clear-btn", onclick: () => app.graph.clear() }), + $el("button", { textContent: "Refresh", className: "comfy-refresh-btn" onclick: () => app.refreshComboInNodes() }), + $el("button", { textContent: "Load Default", className: "comfy-load-default-btn", onclick: () => app.loadGraphData() }), ]); dragElement(this.menuContainer); diff --git a/web/style.css b/web/style.css index 7c3d7efa5..ac56e51e5 100644 --- a/web/style.css +++ b/web/style.css @@ -88,23 +88,48 @@ body { } .comfy-menu { - width: 200px; + width: 250px !important; font-size: 15px; position: absolute; top: 50%; right: 0%; - background-color: white; - color: #000; + background: rgba(68,68,68,0.75); + background: linear-gradient(0deg, rgba(68,68,68,0.75) 0%, rgba(102,102,102,0.75) 74%, rgba(119,119,119,0.75) 100%); + backdrop-filter: blur(30px); + color: #CACACA; text-align: center; + text-shadow: 1px 0 1px rgba(0,0,0,0.25); + font-family: Helvetica; z-index: 100; width: 170px; - display: flex; flex-direction: column; align-items: center; + box-shadow: 0px 0px 30px rgba(0,0,0,0.5); +} + +.comfy-queue-size { + font-size: 18px; + margin-top:5px; } .comfy-menu button { - font-size: 20px; + cursor: pointer; + display: inline !important; + font-size: 18px; + text-shadow: 1px 0 1px rgba(0,0,0,0.25); + font-family: Helvetica; + border-radius: 0; + background-color: #8899aa; + border-left: 0; + border-right: 0; + border-top: 1px solid rgba(255,255,255,0.5); + border-bottom: 1px solid rgba(127,127,127,0.5); + color: #FFF; + transition: background-color .1s ease-in-out +} + +.comfy-menu button:hover { + background-color: #6686a5; } .comfy-menu-btns { @@ -114,7 +139,6 @@ body { .comfy-menu-btns button { font-size: 10px; - width: 50%; } .comfy-menu span.drag-handle { @@ -130,9 +154,9 @@ body { margin-left: -.2em; font-size: 12px; font-family: sans-serif; + text-shadow: 1px 1px 1px rgba(0,0,0,0.25); letter-spacing: 2px; color: #cccccc; - text-shadow: 1px 0 1px black; position: absolute; top: 0; left: 0; @@ -143,18 +167,57 @@ body { } .comfy-queue-btn { + font-size: 20px !important; + font-weight: 600; width: 100%; + background-color: #69b768 !important +} + +.comfy-queue-btn:hover { + background-color: #42b240 !important; +} + +.comfy-queue-front-btn { + width: 50%; + border-right: 1px solid rgba(0,0,0,0.25) !important; +} + +.comfy-view-queue-btn { + width: 50%; + border-left: 1px solid rgba(255,255,255,0.25) !important; +} + +.comfy-history-btn { + width: 100% !important; +} + +.comfy-save-btn { + width: 50%; + border-right: 1px solid rgba(0,0,0,0.25) !important; +} +.comfy-load-btn { + width: 50%; + border-left: 1px solid rgba(255,255,255,0.25) !important; +} + +.comfy-clear-btn { + width: 50%; + border-right: 1px solid rgba(0,0,0,0.25) !important; +} +.comfy-load-default-btn { + width: 50%; + border-left: 1px solid rgba(255,255,255,0.25) !important; } .comfy-list { - background-color: rgb(225, 225, 225); + background-color: rgba(0,0,0,0.25); margin-bottom: 10px; } .comfy-list-items { - overflow-y: scroll; + overflow-y: auto; max-height: 100px; - background-color: #d0d0d0; + background-color: rgba(0,0,0,0.25); padding: 5px; } @@ -186,6 +249,8 @@ button.comfy-settings-btn { position: absolute; right: 0; border: none; + background: none; + line-height: 22px; } .comfy-modal.comfy-settings {