Compare commits

...
13 Commits
Author SHA1 Message Date
Dr.Lt.Data 0f38db4180 feat: support OSS scheduler based on Impact Sampler 2025-04-13 10:31:17 +09:00
Dr.Lt.Data e2d18c21ba feat: IPAdapterModelHelper - add SDXL FaceID Plus v2
https://github.com/ltdrdata/ComfyUI-Inspire-Pack/issues/224
2025-04-05 18:01:42 +09:00
Dr.Lt.Data 13fda9df3f Merge pull request #222 from eltociear/patch-1
docs: update README.md
2025-04-05 01:08:25 +09:00
Ikko Eltociear Ashimine 035f37d1d1 docs: update README.md
minor fix
2025-03-31 00:31:42 +09:00
Dr.Lt.Data 9d179f0193 Merge pull request #220 from ComfyNodePRs/update-publish-yaml
Update Github Action for Publishing to Comfy Registry
2025-03-29 00:32:18 +09:00
Dr.Lt.Data 5891049f2b feat: DropList node is added
https://github.com/ltdrdata/ComfyUI-Inspire-Pack/issues/219
2025-03-25 23:59:53 +09:00
Dr.Lt.Data b35b22d563 improve: ForEachList - display progress of iteration
https://github.com/ltdrdata/ComfyUI-Inspire-Pack/issues/216
2025-03-23 23:29:58 +09:00
Dr.Lt.Data ca5d942cef fixed: backend caches - invalid handling about reserved key '*'
refactoring: ruff fixes
2025-03-03 00:48:53 +09:00
Dr.Lt.Data a9ece5f22e fixed: jxl PR bug
https://github.com/ltdrdata/ComfyUI-Inspire-Pack/pull/212
2025-03-02 16:18:01 +09:00
Dr.Lt.Data a77979c027 Merge pull request #212 from yggdrasil75/patch-1
Update image_util.py
2025-03-02 16:09:43 +09:00
yggdrasil75 20ed3bb5b4 Update image_util.py
add loading jxl with the batch/list nodes
2025-02-27 09:36:38 -05:00
Dr.Lt.Data ecf8ab6f58 feat: noise_mode - add GPU+internal_seed, and CPU+internal_seed mode.
https://github.com/ltdrdata/ComfyUI-Inspire-Pack/issues/208
2025-02-08 14:18:50 +09:00
snomiao f64211c3f3 chore(publish): update GitHub Actions workflow for node publishing
- Add permissions for writing issues
- Update publish-node-action to use version v1
- Add condition to run job only for 'ltdrdata' repository owner
2025-01-21 08:42:07 +00:00
21 changed files with 324 additions and 117 deletions
+6 -2
View File
@@ -7,15 +7,19 @@ on:
paths:
- "pyproject.toml"
permissions:
issues: write
jobs:
publish-node:
name: Publish Custom Node to registry
runs-on: ubuntu-latest
if: ${{ github.repository_owner == 'ltdrdata' }}
steps:
- name: Check out code
uses: actions/checkout@v4
- name: Publish Custom Node
uses: Comfy-Org/publish-node-action@main
uses: Comfy-Org/publish-node-action@v1
with:
## Add your own personal access token to your Github Repository secrets and reference it here.
personal_access_token: ${{ secrets.REGISTRY_ACCESS_TOKEN }}
personal_access_token: ${{ secrets.REGISTRY_ACCESS_TOKEN }}
+4 -2
View File
@@ -2,7 +2,8 @@
This repository offers various extension nodes for ComfyUI. Nodes here have different characteristics compared to those in the ComfyUI Impact Pack. The Impact Pack has become too large now...
## Notice:
* v1.9.1 To avoid confusion with the `NOISE` type in core, the type name has been changed to `NOISE_IMAGE`.
* V1.18: To use the 'OSS' Scheduler, please update to ComfyUI version 0.3.28 or later (April 13th or newer) and Impact Pack version V8.11 or higher.
* V1.9.1 To avoid confusion with the `NOISE` type in core, the type name has been changed to `NOISE_IMAGE`.
* V0.73 The Variation Seed feature is added to Regional Prompt nodes, and it is only compatible with versions Impact Pack V5.10 and above.
* V0.69 incompatible with the outdated **ComfyUI IPAdapter Plus**. (A version dated March 24th or later is required.)
* V0.64 add sigma_factor to RegionalPrompt... nodes required Impact Pack V4.76 or later.
@@ -172,7 +173,8 @@ This repository offers various extension nodes for ComfyUI. Nodes here have diff
* `Float Range (Inspire)`: Create a float list that increases the value by `step` from `start` to `stop`. A list as large as the maximum limit is created, and when `ensure_end` is enabled, the last value of the list becomes the stop value.
* `Worklist To Item List (Inspire)`: The list in ComfyUI allows for repeated execution of a sub-workflow. This groups these repetitions (a.k.a. list) into a single ITEM_LIST output. ITEM_LIST can then be used in ForeachList.
* `▶Foreach List (Inspire)`: A starting node for performing iterative tasks by retrieving items one by one from the ITEM_LIST.\nGenerate a new intermediate_output using item and intermediate_output as inputs, then connect it to ForeachListEnd.\nNOTE:If initial_input is omitted, the first item in item_list is used as the initial value, and the processing starts from the second item in item_list.
* `Foreach List◀ (Inspire)`: A end node for performing iterative tasks by retrieving items one by one from the ITEM_LIST.\nNOTE:Directly connect the outputs of ForeachListBegin to 'flow_control' and 'remained_list'.
* `Foreach List◀ (Inspire)`: An end node for performing iterative tasks by retrieving items one by one from the ITEM_LIST.\nNOTE:Directly connect the outputs of ForeachListBegin to 'flow_control' and 'remained_list'.
* `Drop List (Inspire)`: Removes all items from the ITEM_LIST. If the ITEM_LIST generated through this node is passed to ForeachListEnd, the process is immediately terminated.
### Util - Utilities
* `ToIPAdapterPipe (Inspire)`, `FromIPAdapterPipe (Inspire)`: These nodes assists in conveniently using the bundled ipadapter_model, clip_vision, and model required for applying IPAdapter.
+3 -2
View File
@@ -6,10 +6,11 @@
"""
import importlib
import logging
version_code = [1, 13]
version_code = [1, 18]
version_str = f"V{version_code[0]}.{version_code[1]}" + (f'.{version_code[2]}' if len(version_code) > 2 else '')
print(f"### Loading: ComfyUI-Inspire-Pack ({version_str})")
logging.info(f"### Loading: ComfyUI-Inspire-Pack ({version_str})")
node_list = [
"lora_block_weight",
+18 -11
View File
@@ -5,6 +5,10 @@ from einops import rearrange
import random
import math
from .libs import common
import logging
supported_noise_modes = ["GPU(=A1111)", "CPU", "GPU+internal_seed", "CPU+internal_seed"]
class Inspire_RandomNoise:
@@ -62,7 +66,7 @@ def inspire_ksampler(model, seed, steps, cfg, sampler_name, scheduler, positive,
incremental_seed_mode="comfy", variation_seed=None, variation_strength=None, noise=None, callback=None, variation_method="linear",
scheduler_func=None, internal_seed=None):
device = comfy.model_management.get_torch_device()
noise_device = "cpu" if noise_mode == "CPU" else device
noise_device = "cpu" if 'cpu' in noise_mode.lower() else device
latent_image = latent["samples"]
if hasattr(comfy.sample, 'fix_empty_latent_channels'):
latent_image = comfy.sample.fix_empty_latent_channels(model, latent_image)
@@ -70,7 +74,7 @@ def inspire_ksampler(model, seed, steps, cfg, sampler_name, scheduler, positive,
latent = latent.copy()
if noise is not None and latent_image.shape[1] != noise.shape[1]:
print("[Inspire Pack] inspire_ksampler: The type of latent input for noise generation does not match the model's latent type. When using the SD3 model, you must use the SD3 Empty Latent.")
logging.info("[Inspire Pack] inspire_ksampler: The type of latent input for noise generation does not match the model's latent type. When using the SD3 model, you must use the SD3 Empty Latent.")
raise Exception("The type of latent input for noise generation does not match the model's latent type. When using the SD3 model, you must use the SD3 Empty Latent.")
if noise is None:
@@ -93,17 +97,20 @@ def inspire_ksampler(model, seed, steps, cfg, sampler_name, scheduler, positive,
if internal_seed is None:
internal_seed = seed
if 'internal_seed' in noise_mode:
seed = internal_seed
try:
samples = common.impact_sampling(
model=model, add_noise=not disable_noise, seed=internal_seed, steps=steps, cfg=cfg, sampler_name=sampler_name, scheduler=scheduler, positive=positive, negative=negative,
model=model, add_noise=not disable_noise, seed=seed, steps=steps, cfg=cfg, sampler_name=sampler_name, scheduler=scheduler, positive=positive, negative=negative,
latent_image=latent, start_at_step=start_step, end_at_step=last_step, return_with_leftover_noise=not force_full_denoise, noise=noise, callback=callback,
scheduler_func=scheduler_func)
except Exception as e:
if "unexpected keyword argument 'scheduler_func'" in str(e):
print(f"[Inspire Pack] Impact Pack is outdated. (Cannot use GITS scheduler.)")
logging.info("[Inspire Pack] Impact Pack is outdated. (Cannot use GITS scheduler.)")
samples = common.impact_sampling(
model=model, add_noise=not disable_noise, seed=internal_seed, steps=steps, cfg=cfg, sampler_name=sampler_name, scheduler=scheduler, positive=positive, negative=negative,
model=model, add_noise=not disable_noise, seed=seed, steps=steps, cfg=cfg, sampler_name=sampler_name, scheduler=scheduler, positive=positive, negative=negative,
latent_image=latent, start_at_step=start_step, end_at_step=last_step, return_with_leftover_noise=not force_full_denoise, noise=noise, callback=callback)
else:
raise e
@@ -125,7 +132,7 @@ class KSampler_inspire:
"negative": ("CONDITIONING", ),
"latent_image": ("LATENT", ),
"denoise": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
"noise_mode": (["GPU(=A1111)", "CPU"],),
"noise_mode": (supported_noise_modes,),
"batch_seed_mode": (["incremental", "comfy", "variation str inc:0.01", "variation str inc:0.05"],),
"variation_seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
"variation_strength": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.01}),
@@ -168,7 +175,7 @@ class KSamplerAdvanced_inspire:
"latent_image": ("LATENT", ),
"start_at_step": ("INT", {"default": 0, "min": 0, "max": 10000}),
"end_at_step": ("INT", {"default": 10000, "min": 0, "max": 10000}),
"noise_mode": (["GPU(=A1111)", "CPU"],),
"noise_mode": (supported_noise_modes,),
"return_with_leftover_noise": ("BOOLEAN", {"default": False, "label_on": "enable", "label_off": "disable"}),
"batch_seed_mode": (["incremental", "comfy", "variation str inc:0.01", "variation str inc:0.05"],),
"variation_seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
@@ -223,7 +230,7 @@ class KSampler_inspire_pipe:
"scheduler": (common.SCHEDULERS, ),
"latent_image": ("LATENT", ),
"denoise": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
"noise_mode": (["GPU(=A1111)", "CPU"],),
"noise_mode": (supported_noise_modes,),
"batch_seed_mode": (["incremental", "comfy", "variation str inc:0.01", "variation str inc:0.05"],),
"variation_seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
"variation_strength": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.01}),
@@ -262,7 +269,7 @@ class KSamplerAdvanced_inspire_pipe:
"latent_image": ("LATENT", ),
"start_at_step": ("INT", {"default": 0, "min": 0, "max": 10000}),
"end_at_step": ("INT", {"default": 10000, "min": 0, "max": 10000}),
"noise_mode": (["GPU(=A1111)", "CPU"],),
"noise_mode": (supported_noise_modes,),
"return_with_leftover_noise": ("BOOLEAN", {"default": False, "label_on": "enable", "label_off": "disable"}),
"batch_seed_mode": (["incremental", "comfy", "variation str inc:0.01", "variation str inc:0.05"],),
"variation_seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
@@ -406,7 +413,7 @@ class HyperTileInspire:
nh = random_divisor(h, latent_tile_size * factor, swap_size, rand_obj)
nw = random_divisor(w, latent_tile_size * factor, swap_size, rand_obj)
print(f"factor: {factor} <--- params.depth: {apply_to.index(model_chans)} / scale_depth: {scale_depth} / latent_tile_size={latent_tile_size}")
logging.debug(f"factor: {factor} <--- params.depth: {apply_to.index(model_chans)} / scale_depth: {scale_depth} / latent_tile_size={latent_tile_size}")
# print(f"h: {h}, w:{w} --> nh: {nh}, nw: {nw}")
if nh * nw > 1:
@@ -415,7 +422,7 @@ class HyperTileInspire:
# else:
# temp = None
print(f"q={q} / k={k} / v={v}")
logging.debug(f"q={q} / k={k} / v={v}")
return q, k, v
return q, k, v
+24 -20
View File
@@ -16,7 +16,7 @@ try:
with open(settings_file) as f:
cache_settings = json.load(f)
except Exception as e:
print(e)
logging.error(e)
cache_settings = {}
cache = TaggedCache(cache_settings)
cache_count = {}
@@ -60,11 +60,13 @@ class CacheBackendData:
OUTPUT_NODE = True
def doit(self, key, tag, data):
@staticmethod
def doit(key, tag, data):
global cache
if key == '*':
print(f"[Inspire Pack] CacheBackendData: '*' is reserved key. Cannot use that key")
logging.warning("[Inspire Pack] CacheBackendData: '*' is reserved key. Cannot use that key")
return (None,)
update_cache(key, tag, (False, data))
return (data,)
@@ -90,7 +92,8 @@ class CacheBackendDataNumberKey:
OUTPUT_NODE = True
def doit(self, key, tag, data):
@staticmethod
def doit(key, tag, data):
global cache
update_cache(key, tag, (False, data))
@@ -120,11 +123,13 @@ class CacheBackendDataList:
OUTPUT_NODE = True
def doit(self, key, tag, data):
@staticmethod
def doit(key, tag, data):
global cache
if key == '*':
print(f"[Inspire Pack] CacheBackendDataList: '*' is reserved key. Cannot use that key")
logging.warning("[Inspire Pack] CacheBackendDataList: '*' is reserved key. Cannot use that key")
return (None,)
update_cache(key[0], tag[0], (True, data))
return (data,)
@@ -183,7 +188,7 @@ class RetrieveBackendData:
v = cache.get(key)
if v is None:
print(f"[RetrieveBackendData] '{key}' is unregistered key.")
logging.warning(f"[RetrieveBackendData] '{key}' is unregistered key.")
return (None,)
is_list, data = v[1]
@@ -238,7 +243,7 @@ class RemoveBackendData:
elif key in cache:
del cache[key]
else:
print(f"[Inspire Pack] RemoveBackendData: invalid data key {key}")
logging.warning(f"[Inspire Pack] RemoveBackendData: invalid data key {key}")
return (signal_opt,)
@@ -262,7 +267,7 @@ class RemoveBackendDataNumberKey(RemoveBackendData):
if key in cache:
del cache[key]
else:
print(f"[Inspire Pack] RemoveBackendDataNumberKey: invalid data key {key}")
logging.warning(f"[Inspire Pack] RemoveBackendDataNumberKey: invalid data key {key}")
return (signal_opt,)
@@ -322,7 +327,6 @@ class ShowCachedInfo:
# tag settings is not changed
return
# print(f'set to {new_tag_settings}')
new_cache = TaggedCache(new_tag_settings)
for k, v in cache.items():
new_cache[k] = v
@@ -370,10 +374,10 @@ class CheckpointLoaderSimpleShared(nodes.CheckpointLoaderSimple):
res = self.load_checkpoint(ckpt_name)
update_cache(key, "ckpt", (False, res))
cache_kind = 'ckpt'
print(f"[Inspire Pack] CheckpointLoaderSimpleShared: Ckpt '{ckpt_name}' is cached to '{key}'.")
logging.info(f"[Inspire Pack] CheckpointLoaderSimpleShared: Ckpt '{ckpt_name}' is cached to '{key}'.")
else:
cache_kind, (_, res) = cache[key]
print(f"[Inspire Pack] CheckpointLoaderSimpleShared: Cached ckpt '{key}' is loaded. (Loading skip)")
logging.info(f"[Inspire Pack] CheckpointLoaderSimpleShared: Cached ckpt '{key}' is loaded. (Loading skip)")
if cache_kind == 'ckpt':
model, clip, vae = res
@@ -432,10 +436,10 @@ class LoadDiffusionModelShared(nodes.UNETLoader):
if key not in cache or mode == 'Override Cache':
model = self.load_unet(model_name, weight_dtype)[0]
update_cache(key, "diffusion", (False, model))
print(f"[Inspire Pack] LoadDiffusionModelShared: diffusion model '{model_name}' is cached to '{key}'.")
logging.info(f"[Inspire Pack] LoadDiffusionModelShared: diffusion model '{model_name}' is cached to '{key}'.")
else:
_, (_, model) = cache[key]
print(f"[Inspire Pack] LoadDiffusionModelShared: Cached diffusion model '{key}' is loaded. (Loading skip)")
logging.info(f"[Inspire Pack] LoadDiffusionModelShared: Cached diffusion model '{key}' is loaded. (Loading skip)")
return model, key
@@ -540,10 +544,10 @@ class LoadTextEncoderShared:
res = nodes.NODE_CLASS_MAPPINGS["CLIPLoader"]().load_clip(model_name1, type=type, device=device)[0]
update_cache(key, "diffusion", (False, res))
print(f"[Inspire Pack] LoadTextEncoderShared: text encoder model set is cached to '{key}'.")
logging.info(f"[Inspire Pack] LoadTextEncoderShared: text encoder model set is cached to '{key}'.")
else:
_, (_, res) = cache[key]
print(f"[Inspire Pack] LoadTextEncoderShared: Cached text encoder model set '{key}' is loaded. (Loading skip)")
logging.info(f"[Inspire Pack] LoadTextEncoderShared: Cached text encoder model set '{key}' is loaded. (Loading skip)")
return res, key
@@ -626,10 +630,10 @@ class StableCascade_CheckpointLoader:
if key_b not in cache:
res_b = nodes.CheckpointLoaderSimple().load_checkpoint(ckpt_name=stage_b)
update_cache(key_b, "ckpt", (False, res_b))
print(f"[Inspire Pack] StableCascade_CheckpointLoader: Ckpt '{stage_b}' is cached to '{key_b}'.")
logging.info(f"[Inspire Pack] StableCascade_CheckpointLoader: Ckpt '{stage_b}' is cached to '{key_b}'.")
else:
_, (_, res_b) = cache[key_b]
print(f"[Inspire Pack] StableCascade_CheckpointLoader: Cached ckpt '{key_b}' is loaded. (Loading skip)")
logging.info(f"[Inspire Pack] StableCascade_CheckpointLoader: Cached ckpt '{key_b}' is loaded. (Loading skip)")
b_model, clip, b_vae = res_b
else:
b_model, clip, b_vae = nodes.CheckpointLoaderSimple().load_checkpoint(ckpt_name=stage_b)
@@ -638,10 +642,10 @@ class StableCascade_CheckpointLoader:
if key_c not in cache:
res_c = nodes.unCLIPCheckpointLoader().load_checkpoint(ckpt_name=stage_c)
update_cache(key_c, "unclip_ckpt", (False, res_c))
print(f"[Inspire Pack] StableCascade_CheckpointLoader: Ckpt '{stage_c}' is cached to '{key_c}'.")
logging.info(f"[Inspire Pack] StableCascade_CheckpointLoader: Ckpt '{stage_c}' is cached to '{key_c}'.")
else:
_, (_, res_c) = cache[key_c]
print(f"[Inspire Pack] StableCascade_CheckpointLoader: Cached ckpt '{key_c}' is loaded. (Loading skip)")
logging.info(f"[Inspire Pack] StableCascade_CheckpointLoader: Cached ckpt '{key_c}' is loaded. (Loading skip)")
c_model, _, c_vae, clip_vision = res_c
else:
c_model, _, c_vae, clip_vision = nodes.unCLIPCheckpointLoader().load_checkpoint(ckpt_name=stage_c)
+2 -1
View File
@@ -3,6 +3,7 @@ import nodes
import inspect
from .libs import utils
from nodes import MAX_RESOLUTION
import logging
class ConcatConditioningsWithMultiplier:
@@ -51,7 +52,7 @@ class ConcatConditioningsWithMultiplier:
out = []
if len(conditioning_from) > 1:
print(f"Warning: ConcatConditioningsWithMultiplier {k} contains more than 1 cond, only the first one will actually be applied to conditioning1.")
logging.warning(f"[Inspire Pack] ConcatConditioningsWithMultiplier {k} contains more than 1 cond, only the first one will actually be applied to conditioning1.")
mkey = 'multiplier' + k[12:]
multiplier = float(kwargs[mkey])
+15 -3
View File
@@ -2,11 +2,19 @@ import os
import torch
from PIL import ImageOps
try:
import pillow_jxl # noqa: F401
jxl = True
except ImportError:
jxl = False
import comfy
import folder_paths
import base64
from io import BytesIO
from .libs.utils import *
from .libs.utils import ByPassTypeTuple, empty_pil_tensor, empty_latent
from PIL import Image
import numpy as np
import logging
class LoadImagesFromDirBatch:
@@ -44,6 +52,8 @@ class LoadImagesFromDirBatch:
# Filter files by extension
valid_extensions = ['.jpg', '.jpeg', '.png', '.webp']
if jxl:
valid_extensions.extend('.jxl')
dir_files = [f for f in dir_files if any(f.lower().endswith(ext) for ext in valid_extensions)]
dir_files = sorted(dir_files)
@@ -150,6 +160,8 @@ class LoadImagesFromDirList:
# Filter files by extension
valid_extensions = ['.jpg', '.jpeg', '.png', '.webp']
if jxl:
valid_extensions.extend('.jxl')
dir_files = [f for f in dir_files if any(f.lower().endswith(ext) for ext in valid_extensions)]
dir_files = sorted(dir_files)
@@ -248,7 +260,7 @@ class ChangeImageBatchSize:
output_tensor = input_tensor[:batch_size, :, :, :]
return output_tensor
else:
print(f"[WARN] ChangeImage(Latent)BatchSize: Unknown mode `{mode}` - ignored")
logging.warning(f"[Inspire Pack] ChangeImage(Latent)BatchSize: Unknown mode `{mode}` - ignored")
return input_tensor
@staticmethod
@@ -393,7 +405,7 @@ class ColorMapToMasks:
def doit(self, color_map, max_count, min_pixels):
if len(color_map) > 0:
print(f"[Inspire Pack] WARN: ColorMapToMasks - Sure, here's the translation: `color_map` can only be a single image. Only the first image will be processed. If you want to utilize the remaining images, convert the Image Batch to an Image List.")
logging.warning("[Inspire Pack] ColorMapToMasks - Sure, here's the translation: `color_map` can only be a single image. Only the first image will be processed. If you want to utilize the remaining images, convert the Image Batch to an Image List.")
top_colors = top_k_colors(color_map[0], max_count, min_pixels)
+6 -5
View File
@@ -7,6 +7,7 @@ from . import prompt_support
from aiohttp import web
from . import backend_support
from .libs import common
import logging
max_seed = 2**32 - 1
@@ -50,7 +51,7 @@ async def set_cache_settings(request):
try:
backend_support.ShowCachedInfo.set_cache_settings(data)
return web.Response(text='OK', status=200)
except Exception as e: # pylint: disable=broad-except
except Exception as e:
return web.Response(text=f"{e}", status=500)
@@ -263,9 +264,9 @@ def populate_wildcards(json_data):
if 'ImpactWildcardProcessor' in nodes.NODE_CLASS_MAPPINGS:
if not hasattr(nodes.NODE_CLASS_MAPPINGS['ImpactWildcardProcessor'], 'process'):
print(f"[Inspire Pack] Your Impact Pack is outdated. Please update to the latest version.")
logging.warning("[Inspire Pack] Your Impact Pack is outdated. Please update to the latest version.")
return
wildcard_process = nodes.NODE_CLASS_MAPPINGS['ImpactWildcardProcessor'].process
updated_widget_values = {}
mbp_updated_widget_values = {}
@@ -295,7 +296,7 @@ def populate_wildcards(json_data):
if not isinstance(input_seed, int):
continue
else:
print(f"[Inspire Pack] Only `ImpactInt`, `Seed (rgthree)` and `Primitive` Node are allowed as the seed for '{v['class_type']}'. It will be ignored. ")
logging.warning("[Inspire Pack] Only `ImpactInt`, `Seed (rgthree)` and `Primitive` Node are allowed as the seed for '{v['class_type']}'. It will be ignored. ")
continue
except:
continue
@@ -326,7 +327,7 @@ def populate_wildcards(json_data):
if not isinstance(input_seed, int):
continue
else:
print(f"[Inspire Pack] Only `ImpactInt`, `Seed (rgthree)` and `Primitive` Node are allowed as the seed for '{v['class_type']}'. It will be ignored. ")
logging.warning("[Inspire Pack] Only `ImpactInt`, `Seed (rgthree)` and `Primitive` Node are allowed as the seed for '{v['class_type']}'. It will be ignored. ")
continue
except:
continue
+45 -3
View File
@@ -1,15 +1,18 @@
import comfy
import nodes
from . import utils
import logging
from server import PromptServer
SCHEDULERS = comfy.samplers.KSampler.SCHEDULERS + ['AYS SDXL', 'AYS SD1', 'AYS SVD', "GITS[coeff=1.2]"]
SCHEDULERS = comfy.samplers.KSampler.SCHEDULERS + ['AYS SDXL', 'AYS SD1', 'AYS SVD', "GITS[coeff=1.2]", 'OSS FLUX', 'OSS Wan']
def impact_sampling(*args, **kwargs):
if 'RegionalSampler' not in nodes.NODE_CLASS_MAPPINGS:
utils.try_install_custom_node('https://github.com/ltdrdata/ComfyUI-Impact-Pack',
"'Impact Pack' extension is required.")
raise Exception(f"[ERROR] You need to install 'ComfyUI-Impact-Pack'")
raise Exception("[ERROR] You need to install 'ComfyUI-Impact-Pack'")
return nodes.NODE_CLASS_MAPPINGS['RegionalSampler'].separated_sample(*args, **kwargs)
@@ -36,6 +39,45 @@ def is_changed(uid, value):
changed_cache[uid] = value
print(f"keys: {changed_cache.keys()}")
logging.info(f"keys: {changed_cache.keys()}")
return res
def update_node_status(node, text, progress=None):
if PromptServer.instance.client_id is None:
return
PromptServer.instance.send_sync("inspire/update_status", {
"node": node,
"progress": progress,
"text": text
}, PromptServer.instance.client_id)
class ListWrapper:
def __init__(self, data, aux=None):
if isinstance(data, ListWrapper):
self._data = data
if aux is None:
self.aux = data.aux
else:
self.aux = aux
else:
self._data = list(data)
self.aux = aux
def __getitem__(self, index):
if isinstance(index, slice):
return ListWrapper(self._data[index], self.aux)
else:
return self._data[index]
def __setitem__(self, index, value):
self._data[index] = value
def __len__(self):
return len(self._data)
def __repr__(self):
return f"ListWrapper({self._data}, aux={self.aux})"
+4 -3
View File
@@ -6,6 +6,7 @@ from PIL import Image, ImageDraw
import math
import cv2
import folder_paths
import logging
def apply_variation_noise(latent_image, noise_device, variation_seed, variation_strength, mask=None, variation_method='linear'):
@@ -198,9 +199,9 @@ def try_install_custom_node(custom_node_url, msg):
import cm_global
cm_global.try_call(api='cm.try-install-custom-node',
sender="Inspire Pack", custom_node_url=custom_node_url, msg=msg)
except Exception as e:
print(msg)
print(f"[Inspire Pack] ComfyUI-Manager is outdated. The custom node installation feature is not available.")
except Exception as e: # noqa: F841
logging.error(msg)
logging.error("[Inspire Pack] ComfyUI-Manager is outdated. The custom node installation feature is not available.")
def empty_latent():
+52 -5
View File
@@ -1,5 +1,8 @@
import logging
from comfy_execution.graph_utils import GraphBuilder, is_link
from .libs.utils import any_typ
from .libs.common import update_node_status, ListWrapper
class FloatRange:
@classmethod
@@ -105,11 +108,18 @@ class ForeachListBegin:
if initial_input is None:
initial_input = item_list[0]
item_list = item_list[1:]
if len(item_list) > 0:
return ("stub", item_list[1:], item_list[0], initial_input)
return ("stub", [], None, initial_input)
if len(item_list) > 0:
next_list = ListWrapper(item_list[1:])
next_item = item_list[0]
else:
next_list = ListWrapper([])
next_item = None
if next_list.aux is None:
next_list.aux = len(item_list), None
return "stub", next_list, next_item, initial_input
class ForeachListEnd:
@@ -157,11 +167,18 @@ class ForeachListEnd:
self.collect_contained(child_id, upstream, contained)
def doit(self, flow_control, remained_list, intermediate_output, dynprompt, unique_id):
if hasattr(remained_list, "aux"):
if remained_list.aux[1] is None:
remained_list.aux = (remained_list.aux[0], unique_id)
update_node_status(remained_list.aux[1], f"{(remained_list.aux[0]-len(remained_list))}/{remained_list.aux[0]} steps", (remained_list.aux[0]-len(remained_list))/remained_list.aux[0])
else:
logging.warning("[Inspire Pack] ForeachListEnd: `remained_list` did not come from ForeachList.")
if len(remained_list) == 0:
return (intermediate_output,)
# We want to loop
this_node = dynprompt.get_node(unique_id)
upstream = {}
# Get the list of all nodes between the open and close nodes
@@ -192,6 +209,7 @@ class ForeachListEnd:
node.set_input(k, v)
new_open = graph.lookup_node(open_node)
new_open.set_input("item_list", remained_list)
new_open.set_input("initial_input", intermediate_output)
@@ -204,11 +222,39 @@ class ForeachListEnd:
}
class DropItems:
@classmethod
def INPUT_TYPES(s):
return {
"required": { "item_list": ("ITEM_LIST", {"tooltip":"Directly connect the output of ForeachListBegin, the starting node of the iteration."}), },
}
RETURN_TYPES = (any_typ,)
RETURN_NAMES = ("ITEM_LIST",)
OUTPUT_TOOLTIPS = ("This is the final output value.",)
FUNCTION = "doit"
DESCRIPTION = ""
CATEGORY = "InspirePack/List"
def doit(self, item_list):
l = ListWrapper([])
if hasattr(item_list, 'aux'):
l.aux = item_list.aux
else:
logging.warning("[Inspire Pack] DropItems: `item_list` did not come from ForeachList.")
return (l,)
NODE_CLASS_MAPPINGS = {
"FloatRange //Inspire": FloatRange,
"WorklistToItemList //Inspire": WorklistToItemList,
"ForeachListBegin //Inspire": ForeachListBegin,
"ForeachListEnd //Inspire": ForeachListEnd,
"DropItems //Inspire": DropItems,
}
NODE_DISPLAY_NAME_MAPPINGS = {
@@ -216,4 +262,5 @@ NODE_DISPLAY_NAME_MAPPINGS = {
"WorklistToItemList //Inspire": "Worklist To Item List (Inspire)",
"ForeachListBegin //Inspire": "▶Foreach List (Inspire)",
"ForeachListEnd //Inspire": "Foreach List◀ (Inspire)",
"DropItems //Inspire": "Drop Items (Inspire)",
}
+3 -6
View File
@@ -10,7 +10,7 @@ import json
from comfy.cli_args import args
from safetensors.torch import safe_open
import ast
import logging
from server import PromptServer
from .libs import utils
@@ -51,9 +51,6 @@ def parse_unet_num(s):
class MakeLBW:
def __init__(self):
self.loaded_lora = None
@classmethod
def INPUT_TYPES(s):
preset = ["Preset"] # 20
@@ -573,10 +570,10 @@ class XY_Capsule_LoraBlockWeight:
def set_result(self, image, latent):
if self.another_capsule is not None:
print(f"XY_Capsule_LoraBlockWeight: ({self.another_capsule.x, self.y}) is processed.")
logging.info(f"XY_Capsule_LoraBlockWeight: ({self.another_capsule.x, self.y}) is processed.")
self.storage[(self.another_capsule.x, self.y)] = image
else:
print(f"XY_Capsule_LoraBlockWeight: ({self.x, self.y}) is processed.")
logging.info(f"XY_Capsule_LoraBlockWeight: ({self.x, self.y}) is processed.")
def patch_model(self, model, clip):
lora_name, strength_model, strength_clip, inverse, block_vectors, seed, A, B, heatmap_palette, heatmap_alpha, heatmap_strength, xyplot_mode = self.params
+8 -5
View File
@@ -5,6 +5,8 @@ import server
from .libs import utils
from . import backend_support
from comfy import sdxl_clip
import logging
model_preset = {
# base
@@ -28,6 +30,7 @@ model_preset = {
"SD1.5 FaceID Portrait v11": ("ip-adapter-faceid-portrait-v11_sd15", "CLIP-ViT-H-14-laion2B-s32B-b79K", None, True),
"SD1.5 FaceID Portrait": ("ip-adapter-faceid-portrait_sd15", "CLIP-ViT-H-14-laion2B-s32B-b79K", None, True),
"SDXL FaceID": ("ip-adapter-faceid_sdxl", "CLIP-ViT-H-14-laion2B-s32B-b79K", "ip-adapter-faceid_sdxl_lora", True),
"SDXL FaceID Plus v2": ("ip-adapter-faceid-plusv2_sdxl", "CLIP-ViT-H-14-laion2B-s32B-b79K", "ip-adapter-faceid-plusv2_sdxl_lora", True),
"SDXL FaceID Portrait": ("ip-adapter-faceid-portrait_sdxl", "CLIP-ViT-H-14-laion2B-s32B-b79K", None, True),
"SDXL FaceID Portrait unnorm": ("ip-adapter-faceid-portrait_sdxl_unnorm", "CLIP-ViT-H-14-laion2B-s32B-b79K", None, True),
"Kolors FaceID Plus": ("Kolors-IP-Adapter-FaceID-Plus", "clip-vit-large-patch14-336", None, True),
@@ -48,7 +51,7 @@ def lookup_model(model_dir, name):
if len(resolved_name) > 0:
return resolved_name[0], "OK"
else:
print(f"[ERROR] IPAdapterModelHelper: The `{name}` model file does not exist in `{model_dir}` model dir.")
logging.error(f"[Inspire Pack] IPAdapterModelHelper: The `{name}` model file does not exist in `{model_dir}` model dir.")
return None, "FAIL"
@@ -81,7 +84,7 @@ class IPAdapterModelHelper:
if 'IPAdapter' not in nodes.NODE_CLASS_MAPPINGS:
utils.try_install_custom_node('https://github.com/cubiq/ComfyUI_IPAdapter_plus',
"To use 'IPAdapterModelHelper' node, 'ComfyUI IPAdapter Plus' extension is required.")
raise Exception(f"[ERROR] To use IPAdapterModelHelper, you need to install 'ComfyUI IPAdapter Plus'")
raise Exception("[ERROR] To use IPAdapterModelHelper, you need to install 'ComfyUI IPAdapter Plus'")
is_sdxl_preset = 'SDXL' in preset
if clip is not None:
@@ -95,7 +98,7 @@ class IPAdapterModelHelper:
server.PromptServer.instance.send_sync("inspire-node-output-label", {"node_id": unique_id, "output_idx": 3, "label": "INSIGHTFACE (fail)"})
server.PromptServer.instance.send_sync("inspire-node-output-label", {"node_id": unique_id, "output_idx": 4, "label": "MODEL (fail)"})
server.PromptServer.instance.send_sync("inspire-node-output-label", {"node_id": unique_id, "output_idx": 5, "label": "CLIP (fail)"})
print(f"[ERROR] IPAdapterModelHelper: You cannot mix SDXL and SD1.5 in the checkpoint and IPAdapter.")
logging.error("[Inspire Pack] IPAdapterModelHelper: You cannot mix SDXL and SD1.5 in the checkpoint and IPAdapter.")
raise Exception("[ERROR] You cannot mix SDXL and SD1.5 in the checkpoint and IPAdapter.")
ipadapter, clipvision, lora, is_insightface = model_preset[preset]
@@ -154,13 +157,13 @@ class IPAdapterModelHelper:
if 'IPAdapterInsightFaceLoader' in nodes.NODE_CLASS_MAPPINGS:
insight_face_loader = nodes.NODE_CLASS_MAPPINGS['IPAdapterInsightFaceLoader']().load_insightface
else:
print("'ComfyUI IPAdapter Plus' extension is either too outdated or not installed.")
logging.warning("'ComfyUI IPAdapter Plus' extension is either too outdated or not installed.")
insight_face_loader = None
icache_key = ""
if is_insightface:
if insight_face_loader is None:
raise Exception(f"[ERROR] 'ComfyUI IPAdapter Plus' extension is either too outdated or not installed.")
raise Exception("[ERROR] 'ComfyUI IPAdapter Plus' extension is either too outdated or not installed.")
if cache_mode in ["insightface only", "all"]:
icache_key = 'insightface-' + insightface_provider
+20 -20
View File
@@ -18,6 +18,7 @@ from server import PromptServer
from .libs import utils, common
from .backend_support import CheckpointLoaderSimpleShared
import logging
model_path = folder_paths.models_dir
utils.add_folder_path_and_extensions("inspire_prompts", [os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "prompts"))], {'.txt'})
@@ -39,8 +40,8 @@ try:
with open(pb_yaml_path, 'r', encoding="utf-8") as f:
prompt_builder_preset = yaml.load(f, Loader=yaml.FullLoader)
except Exception as e:
print(f"[Inspire Pack] Failed to load 'prompt-builder.yaml'\nNOTE: Only files with UTF-8 encoding are supported.")
except Exception as e: # noqa: F841
logging.error("[Inspire Pack] Failed to load 'prompt-builder.yaml'\nNOTE: Only files with UTF-8 encoding are supported.")
class LoadPromptsFromDir:
@@ -121,7 +122,7 @@ class LoadPromptsFromDir:
prompts = []
for file_name in prompt_files:
print(f"file_name: {file_name}")
logging.info(f"file_name: {file_name}")
try:
with open(file_name, "r", encoding="utf-8") as file:
prompt_data = file.read()
@@ -138,9 +139,9 @@ class LoadPromptsFromDir:
result_tuple = (positive_text, negative_text, name_text)
prompts.append(result_tuple)
else:
print(f"[WARN] LoadPromptsFromDir: invalid prompt format in '{file_name}'")
logging.warning(f"[Inspire Pack] LoadPromptsFromDir: invalid prompt format in '{file_name}'")
except Exception as e:
print(f"[ERROR] LoadPromptsFromDir: an error occurred while processing '{file_name}': {str(e)}\nNOTE: Only files with UTF-8 encoding are supported.")
logging.error(f"[Inspire Pack] LoadPromptsFromDir: an error occurred while processing '{file_name}': {str(e)}\nNOTE: Only files with UTF-8 encoding are supported.")
# slicing [start_index ~ start_index + load_cap]
total_prompts = len(prompts)
@@ -229,9 +230,9 @@ class LoadPromptsFromFile:
matched_path = None
if matched_path:
print(f"[INFO] LoadPromptsFromFile: file found '{prompt_file}'")
logging.info(f"[Inspire Pack] LoadPromptsFromFile: file found '{prompt_file}'")
else:
print(f"[WARN] LoadPromptsFromFile: file not found '{prompt_file}'")
logging.warning(f"[Inspire Pack] LoadPromptsFromFile: file not found '{prompt_file}'")
prompts = []
try:
@@ -255,9 +256,9 @@ class LoadPromptsFromFile:
result_tuple = (positive_text, negative_text, name_text)
prompts.append(result_tuple)
else:
print(f"[WARN] LoadPromptsFromFile: invalid prompt format in '{prompt_file}'")
logging.warning(f"[Inspire Pack] LoadPromptsFromFile: invalid prompt format in '{prompt_file}'")
except Exception as e:
print(f"[ERROR] LoadPromptsFromFile: an error occurred while processing '{prompt_file}': {str(e)}\nNOTE: Only files with UTF-8 encoding are supported.")
logging.error(f"[Inspire Pack] LoadPromptsFromFile: an error occurred while processing '{prompt_file}': {str(e)}\nNOTE: Only files with UTF-8 encoding are supported.")
# slicing [start_index ~ start_index + load_cap]
total_prompts = len(prompts)
@@ -312,9 +313,9 @@ class LoadSinglePromptFromFile:
prompt_path = None
if prompt_path:
print(f"[INFO] LoadSinglePromptFromFile: file found '{prompt_file}'")
logging.info(f"[Inspire Pack] LoadSinglePromptFromFile: file found '{prompt_file}'")
else:
print(f"[WARN] LoadSinglePromptFromFile: file not found '{prompt_file}'")
logging.warning(f"[Inspire Pack] LoadSinglePromptFromFile: file not found '{prompt_file}'")
prompts = []
try:
@@ -323,7 +324,7 @@ class LoadSinglePromptFromFile:
prompt_data = file.read()
else:
prompt_data = text_data_opt
prompt_list = re.split(r'\n\s*-+\s*\n', prompt_data)
try:
prompt = prompt_list[index]
@@ -340,9 +341,9 @@ class LoadSinglePromptFromFile:
result_tuple = (positive_text, negative_text, name_text)
prompts.append(result_tuple)
else:
print(f"[WARN] LoadSinglePromptFromFile: invalid prompt format in '{prompt_file}'")
logging.warning(f"[Inspire Pack] LoadSinglePromptFromFile: invalid prompt format in '{prompt_file}'")
except Exception as e:
print(f"[ERROR] LoadSinglePromptFromFile: an error occurred while processing '{prompt_file}': {str(e)}\nNOTE: Only files with UTF-8 encoding are supported.")
logging.error(f"[Inspire Pack] LoadSinglePromptFromFile: an error occurred while processing '{prompt_file}': {str(e)}\nNOTE: Only files with UTF-8 encoding are supported.")
return (prompts, )
@@ -563,7 +564,7 @@ class BNK_EncoderWrapper:
if 'BNK_CLIPTextEncodeAdvanced' not in nodes.NODE_CLASS_MAPPINGS:
utils.try_install_custom_node('https://github.com/BlenderNeko/ComfyUI_ADV_CLIP_emb',
"To use 'WildcardEncodeInspire' node, 'ComfyUI_ADV_CLIP_emb' extension is required.")
raise Exception(f"[ERROR] To use WildcardEncodeInspire, you need to install 'Advanced CLIP Text Encode'")
raise Exception("[ERROR] To use WildcardEncodeInspire, you need to install 'Advanced CLIP Text Encode'")
return nodes.NODE_CLASS_MAPPINGS['BNK_CLIPTextEncodeAdvanced']().encode(clip, text, self.token_normalization, self.weight_interpretation)
@@ -604,7 +605,7 @@ class WildcardEncodeInspire:
if 'ImpactWildcardEncode' not in nodes.NODE_CLASS_MAPPINGS:
utils.try_install_custom_node('https://github.com/ltdrdata/ComfyUI-Impact-Pack',
"To use 'Wildcard Encode (Inspire)' node, 'Impact Pack' extension is required.")
raise Exception(f"[ERROR] To use 'Wildcard Encode (Inspire)', you need to install 'Impact Pack'")
raise Exception("[ERROR] To use 'Wildcard Encode (Inspire)', you need to install 'Impact Pack'")
processed = []
model, clip, conditioning = nodes.NODE_CLASS_MAPPINGS['ImpactWildcardEncode'].process_with_loras(wildcard_opt=populated, model=kwargs['model'], clip=kwargs['clip'], seed=kwargs['seed'], clip_encoder=clip_encoder, processed=processed)
@@ -637,7 +638,6 @@ class MakeBasicPipe:
"weight_interpretation": (["comfy", "A1111", "compel", "comfy++", "down_weight"], {'default': 'comfy++'}),
"stop_at_clip_layer": ("INT", {"default": -2, "min": -24, "max": -1, "step": 1}),
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
},
"optional": {
@@ -660,7 +660,7 @@ class MakeBasicPipe:
if 'ImpactWildcardEncode' not in nodes.NODE_CLASS_MAPPINGS:
utils.try_install_custom_node('https://github.com/ltdrdata/ComfyUI-Impact-Pack',
"To use 'Make Basic Pipe (Inspire)' node, 'Impact Pack' extension is required.")
raise Exception(f"[ERROR] To use 'Make Basic Pipe (Inspire)', you need to install 'Impact Pack'")
raise Exception("[ERROR] To use 'Make Basic Pipe (Inspire)', you need to install 'Impact Pack'")
model, clip, vae, key = CheckpointLoaderSimpleShared().doit(ckpt_name=kwargs['ckpt_name'], key_opt=kwargs['ckpt_key_opt'])
clip = nodes.CLIPSetLastLayer().set_last_layer(clip, kwargs['stop_at_clip_layer'])[0]
@@ -738,7 +738,7 @@ class SeedExplorer:
noise = utils.apply_variation_noise(noise, noise_device, variation_seed, variation_strength, mask=mask, variation_method=variation_method)
except Exception:
print(f"[ERROR] IGNORED: SeedExplorer failed to processing '{x}'")
logging.error(f"[Inspire Pack] IGNORED: SeedExplorer failed to processing '{x}'")
traceback.print_exc()
return noise
@@ -779,7 +779,7 @@ class SeedExplorer:
return (noise,)
except Exception:
print(f"[ERROR] IGNORED: SeedExplorer failed")
logging.error("[Inspire Pack] IGNORED: SeedExplorer failed")
traceback.print_exc()
noise = torch.zeros(latent_image.size(), dtype=latent_image.dtype, layout=latent_image.layout,
+7 -7
View File
@@ -9,6 +9,7 @@ import webcolors
from . import prompt_support
from .libs import utils, common
import logging
class RegionalPromptSimple:
@classmethod
@@ -43,7 +44,7 @@ class RegionalPromptSimple:
if 'RegionalPrompt' not in nodes.NODE_CLASS_MAPPINGS:
utils.try_install_custom_node('https://github.com/ltdrdata/ComfyUI-Impact-Pack',
"To use 'RegionalPromptSimple' node, 'Impact Pack' extension is required.")
raise Exception(f"[ERROR] To use RegionalPromptSimple, you need to install 'ComfyUI-Impact-Pack'")
raise Exception("[ERROR] To use RegionalPromptSimple, you need to install 'ComfyUI-Impact-Pack'")
model, clip, vae, positive, negative = basic_pipe
@@ -88,7 +89,7 @@ def color_to_mask(color_mask, mask_color):
else:
selected = int(mask_color, 10)
except Exception:
raise Exception(f"[ERROR] Invalid mask_color value. mask_color should be a color value for RGB")
raise Exception("[ERROR] Invalid mask_color value. mask_color should be a color value for RGB")
temp = (torch.clamp(color_mask, 0, 1.0) * 255.0).round().to(torch.int)
temp = torch.bitwise_left_shift(temp[:, :, :, 0], 16) + torch.bitwise_left_shift(temp[:, :, :, 1], 8) + temp[:, :, :, 2]
@@ -260,7 +261,7 @@ class IPAdapterConditioning:
if 'IPAdapterAdvanced' not in nodes.NODE_CLASS_MAPPINGS:
utils.try_install_custom_node('https://github.com/cubiq/ComfyUI_IPAdapter_plus',
"To use 'Regional IPAdapter' node, 'ComfyUI IPAdapter Plus' extension is required.")
raise Exception(f"[ERROR] To use IPAdapterModelHelper, you need to install 'ComfyUI IPAdapter Plus'")
raise Exception("[ERROR] To use IPAdapterModelHelper, you need to install 'ComfyUI IPAdapter Plus'")
if self.embeds is None:
obj = nodes.NODE_CLASS_MAPPINGS['IPAdapterAdvanced']
@@ -287,7 +288,7 @@ def IPADAPTER_WEIGHT_TYPES():
try:
IPADAPTER_WEIGHT_TYPES_CACHE = nodes.NODE_CLASS_MAPPINGS['IPAdapterAdvanced']().INPUT_TYPES()['required']['weight_type'][0]
except Exception:
print(f"[Inspire Pack] IPAdapterPlus is not installed.")
logging.error("[Inspire Pack] IPAdapterPlus is not installed.")
IPADAPTER_WEIGHT_TYPES_CACHE = ["IPAdapterPlus is not installed"]
return IPADAPTER_WEIGHT_TYPES_CACHE
@@ -334,7 +335,6 @@ class RegionalIPAdapterColorMask:
"required": {
"color_mask": ("IMAGE",),
"mask_color": ("STRING", {"multiline": False, "default": "#FFFFFF"}),
"image": ("IMAGE",),
"weight": ("FLOAT", {"default": 0.7, "min": -1, "max": 3, "step": 0.05}),
"noise": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 1.0, "step": 0.01}),
@@ -501,7 +501,7 @@ class RegionalSeedExplorerMask:
noise = prompt_support.SeedExplorer.apply_variation(noise, items, noise_device, mask, variation_method=variation_method)
except Exception:
print(f"[ERROR] IGNORED: RegionalSeedExplorerColorMask is failed.")
logging.error("[Inspire Pack] IGNORED: RegionalSeedExplorerColorMask is failed.")
traceback.print_exc()
noise = noise.cpu()
@@ -559,7 +559,7 @@ class RegionalSeedExplorerColorMask:
noise = prompt_support.SeedExplorer.apply_variation(noise, items, noise_device, mask, variation_method=variation_method)
except Exception:
print(f"[ERROR] IGNORED: RegionalSeedExplorerColorMask is failed.")
logging.error("[Inspire Pack] IGNORED: RegionalSeedExplorerColorMask is failed.")
traceback.print_exc()
color_mask.cpu()
+3 -3
View File
@@ -2,11 +2,11 @@ import torch
from . import a1111_compat
import comfy
from .libs import common
from comfy import model_management
from comfy.samplers import CFGGuider
from comfy_extras.nodes_perpneg import Guider_PerpNeg
import math
class KSampler_progress(a1111_compat.KSampler_inspire):
@classmethod
def INPUT_TYPES(s):
@@ -21,7 +21,7 @@ class KSampler_progress(a1111_compat.KSampler_inspire):
"negative": ("CONDITIONING", ),
"latent_image": ("LATENT", ),
"denoise": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
"noise_mode": (["GPU(=A1111)", "CPU"],),
"noise_mode": (a1111_compat.supported_noise_modes,),
"interval": ("INT", {"default": 1, "min": 1, "max": 10000}),
"omit_start_latent": ("BOOLEAN", {"default": True, "label_on": "True", "label_off": "False"}),
"omit_final_latent": ("BOOLEAN", {"default": False, "label_on": "True", "label_off": "False"}),
@@ -85,7 +85,7 @@ class KSamplerAdvanced_progress(a1111_compat.KSamplerAdvanced_inspire):
"latent_image": ("LATENT", ),
"start_at_step": ("INT", {"default": 0, "min": 0, "max": 10000}),
"end_at_step": ("INT", {"default": 10000, "min": 0, "max": 10000}),
"noise_mode": (["GPU(=A1111)", "CPU"],),
"noise_mode": (a1111_compat.supported_noise_modes,),
"return_with_leftover_noise": ("BOOLEAN", {"default": False, "label_on": "enable", "label_off": "disable"}),
"interval": ("INT", {"default": 1, "min": 1, "max": 10000}),
"omit_start_latent": ("BOOLEAN", {"default": False, "label_on": "True", "label_off": "False"}),
+18 -18
View File
@@ -2,7 +2,7 @@ import nodes
import numpy as np
import torch
from .libs import utils
import logging
def normalize_size_base_64(w, h):
short_side = min(w, h)
@@ -28,12 +28,12 @@ class MediaPipeFaceMeshDetector:
if 'MediaPipe-FaceMeshPreprocessor' not in nodes.NODE_CLASS_MAPPINGS:
utils.try_install_custom_node('https://github.com/Fannovel16/comfyui_controlnet_aux',
"To use 'MediaPipeFaceMeshDetector' node, 'ComfyUI's ControlNet Auxiliary Preprocessors.' extension is required.")
raise Exception(f"[ERROR] To use MediaPipeFaceMeshDetector, you need to install 'ComfyUI's ControlNet Auxiliary Preprocessors.'")
raise Exception("[ERROR] To use MediaPipeFaceMeshDetector, you need to install 'ComfyUI's ControlNet Auxiliary Preprocessors.'")
if 'MediaPipeFaceMeshToSEGS' not in nodes.NODE_CLASS_MAPPINGS:
utils.try_install_custom_node('https://github.com/ltdrdata/ComfyUI-Impact-Pack',
"To use 'MediaPipeFaceMeshDetector' node, 'Impact Pack' extension is required.")
raise Exception(f"[ERROR] To use MediaPipeFaceMeshDetector, you need to install 'ComfyUI-Impact-Pack'")
raise Exception("[ERROR] To use MediaPipeFaceMeshDetector, you need to install 'ComfyUI-Impact-Pack'")
pre_obj = nodes.NODE_CLASS_MAPPINGS['MediaPipe-FaceMeshPreprocessor']
seg_obj = nodes.NODE_CLASS_MAPPINGS['MediaPipeFaceMeshToSEGS']
@@ -63,7 +63,7 @@ class MediaPipe_FaceMesh_Preprocessor_wrapper:
if 'MediaPipe-FaceMeshPreprocessor' not in nodes.NODE_CLASS_MAPPINGS:
utils.try_install_custom_node('https://github.com/Fannovel16/comfyui_controlnet_aux',
"To use 'MediaPipe_FaceMesh_Preprocessor_Provider_for_SEGS' node, 'ComfyUI's ControlNet Auxiliary Preprocessors.' extension is required.")
raise Exception(f"[ERROR] To use MediaPipe_FaceMesh_Preprocessor_Provider_for_SEGS, you need to install 'ComfyUI's ControlNet Auxiliary Preprocessors.'")
raise Exception("[ERROR] To use MediaPipe_FaceMesh_Preprocessor_Provider_for_SEGS, you need to install 'ComfyUI's ControlNet Auxiliary Preprocessors.'")
if self.upscale_factor != 1.0:
image = nodes.ImageScaleBy().upscale(image, 'bilinear', self.upscale_factor)[0]
@@ -78,7 +78,7 @@ class AnimeLineArt_Preprocessor_wrapper:
if 'AnimeLineArtPreprocessor' not in nodes.NODE_CLASS_MAPPINGS:
utils.try_install_custom_node('https://github.com/Fannovel16/comfyui_controlnet_aux',
"To use 'AnimeLineArt_Preprocessor_Provider' node, 'ComfyUI's ControlNet Auxiliary Preprocessors.' extension is required.")
raise Exception(f"[ERROR] To use AnimeLineArt_Preprocessor_Provider, you need to install 'ComfyUI's ControlNet Auxiliary Preprocessors.'")
raise Exception("[ERROR] To use AnimeLineArt_Preprocessor_Provider, you need to install 'ComfyUI's ControlNet Auxiliary Preprocessors.'")
obj = nodes.NODE_CLASS_MAPPINGS['AnimeLineArtPreprocessor']()
resolution = normalize_size_base_64(image.shape[2], image.shape[1])
@@ -90,7 +90,7 @@ class Manga2Anime_LineArt_Preprocessor_wrapper:
if 'Manga2Anime_LineArt_Preprocessor' not in nodes.NODE_CLASS_MAPPINGS:
utils.try_install_custom_node('https://github.com/Fannovel16/comfyui_controlnet_aux',
"To use 'Manga2Anime_LineArt_Preprocessor_Provider' node, 'ComfyUI's ControlNet Auxiliary Preprocessors.' extension is required.")
raise Exception(f"[ERROR] To use Manga2Anime_LineArt_Preprocessor_Provider, you need to install 'ComfyUI's ControlNet Auxiliary Preprocessors.'")
raise Exception("[ERROR] To use Manga2Anime_LineArt_Preprocessor_Provider, you need to install 'ComfyUI's ControlNet Auxiliary Preprocessors.'")
obj = nodes.NODE_CLASS_MAPPINGS['Manga2Anime_LineArt_Preprocessor']()
resolution = normalize_size_base_64(image.shape[2], image.shape[1])
@@ -102,7 +102,7 @@ class Color_Preprocessor_wrapper:
if 'ColorPreprocessor' not in nodes.NODE_CLASS_MAPPINGS:
utils.try_install_custom_node('https://github.com/Fannovel16/comfyui_controlnet_aux',
"To use 'Color_Preprocessor_Provider' node, 'ComfyUI's ControlNet Auxiliary Preprocessors.' extension is required.")
raise Exception(f"[ERROR] To use Color_Preprocessor_Provider, you need to install 'ComfyUI's ControlNet Auxiliary Preprocessors.'")
raise Exception("[ERROR] To use Color_Preprocessor_Provider, you need to install 'ComfyUI's ControlNet Auxiliary Preprocessors.'")
obj = nodes.NODE_CLASS_MAPPINGS['ColorPreprocessor']()
resolution = normalize_size_base_64(image.shape[2], image.shape[1])
@@ -112,12 +112,12 @@ class Color_Preprocessor_wrapper:
class InpaintPreprocessor_wrapper:
def __init__(self, black_pixel_for_xinsir_cn):
self.black_pixel_for_xinsir_cn = black_pixel_for_xinsir_cn
def apply(self, image, mask=None):
if 'InpaintPreprocessor' not in nodes.NODE_CLASS_MAPPINGS:
utils.try_install_custom_node('https://github.com/Fannovel16/comfyui_controlnet_aux',
"To use 'InpaintPreprocessor_Provider' node, 'ComfyUI's ControlNet Auxiliary Preprocessors.' extension is required.")
raise Exception(f"[ERROR] To use InpaintPreprocessor_Provider, you need to install 'ComfyUI's ControlNet Auxiliary Preprocessors.'")
raise Exception("[ERROR] To use InpaintPreprocessor_Provider, you need to install 'ComfyUI's ControlNet Auxiliary Preprocessors.'")
obj = nodes.NODE_CLASS_MAPPINGS['InpaintPreprocessor']()
if mask is None:
@@ -130,7 +130,7 @@ class InpaintPreprocessor_wrapper:
raise e
else:
res = obj.preprocess(image, mask)[0]
print(f"[Inspire Pack] Installed 'ComfyUI's ControlNet Auxiliary Preprocessors.' is outdated.")
logging.warning("[Inspire Pack] Installed 'ComfyUI's ControlNet Auxiliary Preprocessors.' is outdated.")
return res
@@ -143,7 +143,7 @@ class TilePreprocessor_wrapper:
if 'TilePreprocessor' not in nodes.NODE_CLASS_MAPPINGS:
utils.try_install_custom_node('https://github.com/Fannovel16/comfyui_controlnet_aux',
"To use 'TilePreprocessor_Provider' node, 'ComfyUI's ControlNet Auxiliary Preprocessors.' extension is required.")
raise Exception(f"[ERROR] To use TilePreprocessor_Provider, you need to install 'ComfyUI's ControlNet Auxiliary Preprocessors.'")
raise Exception("[ERROR] To use TilePreprocessor_Provider, you need to install 'ComfyUI's ControlNet Auxiliary Preprocessors.'")
obj = nodes.NODE_CLASS_MAPPINGS['TilePreprocessor']()
resolution = normalize_size_base_64(image.shape[2], image.shape[1])
@@ -155,7 +155,7 @@ class MeshGraphormerDepthMapPreprocessorProvider_wrapper:
if 'MeshGraphormer-DepthMapPreprocessor' not in nodes.NODE_CLASS_MAPPINGS:
utils.try_install_custom_node('https://github.com/Fannovel16/comfyui_controlnet_aux',
"To use 'MeshGraphormerDepthMapPreprocessorProvider' node, 'ComfyUI's ControlNet Auxiliary Preprocessors.' extension is required.")
raise Exception(f"[ERROR] To use MeshGraphormerDepthMapPreprocessorProvider, you need to install 'ComfyUI's ControlNet Auxiliary Preprocessors.'")
raise Exception("[ERROR] To use MeshGraphormerDepthMapPreprocessorProvider, you need to install 'ComfyUI's ControlNet Auxiliary Preprocessors.'")
obj = nodes.NODE_CLASS_MAPPINGS['MeshGraphormer-DepthMapPreprocessor']()
resolution = normalize_size_base_64(image.shape[2], image.shape[1])
@@ -170,7 +170,7 @@ class LineArt_Preprocessor_wrapper:
if 'LineArtPreprocessor' not in nodes.NODE_CLASS_MAPPINGS:
utils.try_install_custom_node('https://github.com/Fannovel16/comfyui_controlnet_aux',
"To use 'LineArt_Preprocessor_Provider' node, 'ComfyUI's ControlNet Auxiliary Preprocessors.' extension is required.")
raise Exception(f"[ERROR] To use LineArt_Preprocessor_Provider, you need to install 'ComfyUI's ControlNet Auxiliary Preprocessors.'")
raise Exception("[ERROR] To use LineArt_Preprocessor_Provider, you need to install 'ComfyUI's ControlNet Auxiliary Preprocessors.'")
coarse = 'enable' if self.coarse else 'disable'
@@ -190,7 +190,7 @@ class OpenPose_Preprocessor_wrapper:
if 'OpenposePreprocessor' not in nodes.NODE_CLASS_MAPPINGS:
utils.try_install_custom_node('https://github.com/Fannovel16/comfyui_controlnet_aux',
"To use 'OpenPose_Preprocessor_Provider' node, 'ComfyUI's ControlNet Auxiliary Preprocessors.' extension is required.")
raise Exception(f"[ERROR] To use OpenPose_Preprocessor_Provider, you need to install 'ComfyUI's ControlNet Auxiliary Preprocessors.'")
raise Exception("[ERROR] To use OpenPose_Preprocessor_Provider, you need to install 'ComfyUI's ControlNet Auxiliary Preprocessors.'")
detect_hand = 'enable' if self.detect_hand else 'disable'
detect_body = 'enable' if self.detect_body else 'disable'
@@ -217,7 +217,7 @@ class DWPreprocessor_wrapper:
if 'DWPreprocessor' not in nodes.NODE_CLASS_MAPPINGS:
utils.try_install_custom_node('https://github.com/Fannovel16/comfyui_controlnet_aux',
"To use 'DWPreprocessor_Provider' node, 'ComfyUI's ControlNet Auxiliary Preprocessors.' extension is required.")
raise Exception(f"[ERROR] To use DWPreprocessor_Provider, you need to install 'ComfyUI's ControlNet Auxiliary Preprocessors.'")
raise Exception("[ERROR] To use DWPreprocessor_Provider, you need to install 'ComfyUI's ControlNet Auxiliary Preprocessors.'")
detect_hand = 'enable' if self.detect_hand else 'disable'
detect_body = 'enable' if self.detect_body else 'disable'
@@ -241,7 +241,7 @@ class LeReS_DepthMap_Preprocessor_wrapper:
if 'LeReS-DepthMapPreprocessor' not in nodes.NODE_CLASS_MAPPINGS:
utils.try_install_custom_node('https://github.com/Fannovel16/comfyui_controlnet_aux',
"To use 'LeReS_DepthMap_Preprocessor_Provider' node, 'ComfyUI's ControlNet Auxiliary Preprocessors.' extension is required.")
raise Exception(f"[ERROR] To use LeReS_DepthMap_Preprocessor_Provider, you need to install 'ComfyUI's ControlNet Auxiliary Preprocessors.'")
raise Exception("[ERROR] To use LeReS_DepthMap_Preprocessor_Provider, you need to install 'ComfyUI's ControlNet Auxiliary Preprocessors.'")
boost = 'enable' if self.boost else 'disable'
@@ -259,7 +259,7 @@ class MiDaS_DepthMap_Preprocessor_wrapper:
if 'MiDaS-DepthMapPreprocessor' not in nodes.NODE_CLASS_MAPPINGS:
utils.try_install_custom_node('https://github.com/Fannovel16/comfyui_controlnet_aux',
"To use 'MiDaS_DepthMap_Preprocessor_Provider' node, 'ComfyUI's ControlNet Auxiliary Preprocessors.' extension is required.")
raise Exception(f"[ERROR] To use MiDaS_DepthMap_Preprocessor_Provider, you need to install 'ComfyUI's ControlNet Auxiliary Preprocessors.'")
raise Exception("[ERROR] To use MiDaS_DepthMap_Preprocessor_Provider, you need to install 'ComfyUI's ControlNet Auxiliary Preprocessors.'")
obj = nodes.NODE_CLASS_MAPPINGS['MiDaS-DepthMapPreprocessor']()
resolution = normalize_size_base_64(image.shape[2], image.shape[1])
@@ -271,7 +271,7 @@ class Zoe_DepthMap_Preprocessor_wrapper:
if 'Zoe-DepthMapPreprocessor' not in nodes.NODE_CLASS_MAPPINGS:
utils.try_install_custom_node('https://github.com/Fannovel16/comfyui_controlnet_aux',
"To use 'Zoe_DepthMap_Preprocessor_Provider' node, 'ComfyUI's ControlNet Auxiliary Preprocessors.' extension is required.")
raise Exception(f"[ERROR] To use Zoe_DepthMap_Preprocessor_Provider, you need to install 'ComfyUI's ControlNet Auxiliary Preprocessors.'")
raise Exception("[ERROR] To use Zoe_DepthMap_Preprocessor_Provider, you need to install 'ComfyUI's ControlNet Auxiliary Preprocessors.'")
obj = nodes.NODE_CLASS_MAPPINGS['Zoe-DepthMapPreprocessor']()
resolution = normalize_size_base_64(image.shape[2], image.shape[1])
+7
View File
@@ -0,0 +1,7 @@
import { inspireProgressBadge } from "./progress-badge.js"
export function register_loop_node(nodeType, nodeData, app) {
if(nodeData.name == 'ForeachListEnd //Inspire') {
inspireProgressBadge.addStatusHandler(nodeType);
}
}
+2
View File
@@ -1,11 +1,13 @@
import { ComfyApp, app } from "../../scripts/app.js";
import { register_concat_conditionings_with_multiplier_node, register_splitter } from "./inspire-flex.js";
import { register_cache_info } from "./inspire-backend.js";
import { register_loop_node } from "./inspire-loop.js";
app.registerExtension({
name: "Comfy.Inspire",
async beforeRegisterNodeDef(nodeType, nodeData, app) {
await register_concat_conditionings_with_multiplier_node(nodeType, nodeData, app);
await register_loop_node(nodeType, nodeData, app);
},
nodeCreated(node, app) {
+76
View File
@@ -0,0 +1,76 @@
import { api } from "../../scripts/api.js";
// copying from https://github.com/pythongosssss/ComfyUI-WD14-Tagger
class InspireProgressBadge {
constructor() {
if (!window.__progress_badge__) {
window.__progress_badge__ = Symbol("__inspire_progress_badge__");
}
this.symbol = window.__progress_badge__;
}
getState(node) {
return node[this.symbol] || {};
}
setState(node, state) {
node[this.symbol] = state;
app.canvas.setDirty(true);
}
addStatusHandler(nodeType) {
if (nodeType[this.symbol]?.statusTagHandler) {
return;
}
if (!nodeType[this.symbol]) {
nodeType[this.symbol] = {};
}
nodeType[this.symbol] = {
statusTagHandler: true,
};
api.addEventListener("inspire/update_status", ({ detail }) => {
let { node, progress, text } = detail;
const n = app.graph.getNodeById(+(node || app.runningNodeId));
if (!n) return;
const state = this.getState(n);
state.status = Object.assign(state.status || {}, { progress: text ? progress : null, text: text || null });
this.setState(n, state);
});
const self = this;
const onDrawForeground = nodeType.prototype.onDrawForeground;
nodeType.prototype.onDrawForeground = function (ctx) {
const r = onDrawForeground?.apply?.(this, arguments);
const state = self.getState(this);
if (!state?.status?.text) {
return r;
}
const { fgColor, bgColor, text, progress, progressColor } = { ...state.status };
ctx.save();
ctx.font = "12px sans-serif";
const sz = ctx.measureText(text);
ctx.fillStyle = bgColor || "dodgerblue";
ctx.beginPath();
ctx.roundRect(0, -LiteGraph.NODE_TITLE_HEIGHT - 20, sz.width + 12, 20, 5);
ctx.fill();
if (progress) {
ctx.fillStyle = progressColor || "green";
ctx.beginPath();
ctx.roundRect(0, -LiteGraph.NODE_TITLE_HEIGHT - 20, (sz.width + 12) * progress, 20, 5);
ctx.fill();
}
ctx.fillStyle = fgColor || "#fff";
ctx.fillText(text, 6, -LiteGraph.NODE_TITLE_HEIGHT - 6);
ctx.restore();
return r;
};
}
}
export const inspireProgressBadge = new InspireProgressBadge();
+1 -1
View File
@@ -1,7 +1,7 @@
[project]
name = "comfyui-inspire-pack"
description = "This extension provides various nodes to support Lora Block Weight, Regional Nodes, Backend Cache, Prompt Utils, List Utils, Noise(Seed) Utils, ... and the Impact Pack."
version = "1.13"
version = "1.18"
license = { file = "LICENSE" }
dependencies = ["matplotlib", "cachetools"]