Compare commits

..
6 Commits
Author SHA1 Message Date
Dr.Lt.Data 3fc749d6ba feat: Load Image Batch/List from Dir - sort_method is added
https://github.com/ltdrdata/ComfyUI-Inspire-Pack/issues/233
2025-06-17 22:05:16 +09:00
Dr.Lt.Data c2ccf7f879 Merge pull request #240 from LevelPixel/patch-1
Return an empty list from RetrieveBackendData rather than throwing a runtime error
2025-06-12 17:05:51 +09:00
Level Pixel 8e99bebdfe Update backend_support.py - Return an empty list rather than throwing a runtime error
Return an empty list rather than throwing a runtime error
2025-06-10 06:51:57 +06:00
Dr.Lt.Data 8814b8901a modified: support case-insensitive matching for prompt loader
https://github.com/ltdrdata/ComfyUI-Inspire-Pack/issues/239#issuecomment-2952226907
2025-06-09 06:30:31 +09:00
Dr.Lt.Data 291d3dd13f Merge pull request #230 from wzgrx/patch-1
Update requirements.txt
2025-05-17 16:57:27 +09:00
wzgrx 5619e51b01 Update requirements.txt 2025-05-17 09:28:41 +08:00
6 changed files with 87 additions and 20 deletions
+1 -11
View File
@@ -8,7 +8,7 @@
import importlib
import logging
version_code = [1, 18]
version_code = [1, 20]
version_str = f"V{version_code[0]}.{version_code[1]}" + (f'.{version_code[2]}' if len(version_code) > 2 else '')
logging.info(f"### Loading: ComfyUI-Inspire-Pack ({version_str})")
@@ -39,13 +39,3 @@ for module_name in node_list:
WEB_DIRECTORY = "./js"
__all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS", "WEB_DIRECTORY"]
try:
import cm_global
cm_global.register_extension('ComfyUI-Inspire-Pack',
{'version': version_code,
'name': 'Inspire Pack',
'nodes': set(NODE_CLASS_MAPPINGS.keys()),
'description': 'This extension provides various nodes to support Lora Block Weight and the Impact Pack. Provides many easily applicable regional features and applications for Variation Seed.', })
except:
pass
+1 -1
View File
@@ -189,7 +189,7 @@ class RetrieveBackendData:
if v is None:
logging.warning(f"[RetrieveBackendData] '{key}' is unregistered key.")
return (None,)
return ([None],)
is_list, data = v[1]
+48 -4
View File
@@ -15,6 +15,48 @@ from .libs.utils import ByPassTypeTuple, empty_pil_tensor, empty_latent
from PIL import Image
import numpy as np
import logging
import re
def extract_first_number(s):
match = re.search(r'\d+', s)
return int(match.group()) if match else float('inf')
sort_methods = [
"None",
"Alphabetical (ASC)",
"Alphabetical (DESC)",
"Numerical (ASC)",
"Numerical (DESC)",
"Datetime (ASC)",
"Datetime (DESC)"
]
def sort_by(items, base_path='.', method=None):
def fullpath(x): return os.path.join(base_path, x)
def get_timestamp(path):
try:
return os.path.getmtime(path)
except FileNotFoundError:
return float('-inf')
if method == "Alphabetical (ASC)":
return sorted(items)
elif method == "Alphabetical (DESC)":
return sorted(items, reverse=True)
elif method == "Numerical (ASC)":
return sorted(items, key=lambda x: extract_first_number(os.path.splitext(x)[0]))
elif method == "Numerical (DESC)":
return sorted(items, key=lambda x: extract_first_number(os.path.splitext(x)[0]), reverse=True)
elif method == "Datetime (ASC)":
return sorted(items, key=lambda x: get_timestamp(fullpath(x)))
elif method == "Datetime (DESC)":
return sorted(items, key=lambda x: get_timestamp(fullpath(x)), reverse=True)
else:
return items
class LoadImagesFromDirBatch:
@@ -28,6 +70,7 @@ class LoadImagesFromDirBatch:
"image_load_cap": ("INT", {"default": 0, "min": 0, "step": 1}),
"start_index": ("INT", {"default": 0, "min": -1, "max": 0xffffffffffffffff, "step": 1}),
"load_always": ("BOOLEAN", {"default": False, "label_on": "enabled", "label_off": "disabled"}),
"sort_method": (sort_methods,),
}
}
@@ -43,7 +86,7 @@ class LoadImagesFromDirBatch:
else:
return hash(frozenset(kwargs))
def load_images(self, directory: str, image_load_cap: int = 0, start_index: int = 0, load_always=False):
def load_images(self, directory: str, image_load_cap: int = 0, start_index: int = 0, load_always=False, sort_method=None):
if not os.path.isdir(directory):
raise FileNotFoundError(f"Directory '{directory} cannot be found.'")
dir_files = os.listdir(directory)
@@ -56,7 +99,7 @@ class LoadImagesFromDirBatch:
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)
dir_files = sort_by(dir_files, directory, sort_method)
dir_files = [os.path.join(directory, x) for x in dir_files]
# start at start_index
@@ -133,6 +176,7 @@ class LoadImagesFromDirList:
"image_load_cap": ("INT", {"default": 0, "min": 0, "step": 1}),
"start_index": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff, "step": 1}),
"load_always": ("BOOLEAN", {"default": False, "label_on": "enabled", "label_off": "disabled"}),
"sort_method": (sort_methods,),
}
}
@@ -151,7 +195,7 @@ class LoadImagesFromDirList:
else:
return hash(frozenset(kwargs))
def load_images(self, directory: str, image_load_cap: int = 0, start_index: int = 0, load_always=False):
def load_images(self, directory: str, image_load_cap: int = 0, start_index: int = 0, load_always=False, sort_method=None):
if not os.path.isdir(directory):
raise FileNotFoundError(f"Directory '{directory}' cannot be found.")
dir_files = os.listdir(directory)
@@ -164,7 +208,7 @@ class LoadImagesFromDirList:
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)
dir_files = sort_by(dir_files, directory, sort_method)
dir_files = [os.path.join(directory, x) for x in dir_files]
# start at start_index
+35 -2
View File
@@ -130,7 +130,7 @@ class LoadPromptsFromDir:
for prompt in prompt_list:
pattern = r"^(?:(?:positive:(?P<positive>.*?)|negative:(?P<negative>.*?)|name:(?P<name>.*?))\n*)+$"
matches = re.search(pattern, prompt, re.DOTALL)
matches = re.search(pattern, prompt, re.DOTALL | re.IGNORECASE)
if matches:
positive_text = matches.group('positive').strip()
@@ -487,6 +487,37 @@ class GlobalSeed:
return {}
class SeedLogger:
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
"seeds": ("STRING", {"multiline": True, "dynamicPrompts": False, "control_after_generate": False}),
"limit": ("INT", {"default": 5, "min": 0, "max": 0xffffffffffffffff}),
},
"hidden": {"unique_id": "UNIQUE_ID"}
}
RETURN_TYPES = ()
FUNCTION = "doit"
CATEGORY = "InspirePack/Prompt"
OUTPUT_NODE = True
def doit(self, seed, seeds: str, limit, unique_id):
if limit > 0:
lines = seeds.split('\n')
res = str(seed) + '\n' + '\n'.join(lines[:limit-1])
else:
res = str(seed) + '\n' + seeds
PromptServer.instance.send_sync("inspire-node-feedback", {"node_id": unique_id, "widget_name": "seeds", "type": "text", "data": res})
return {}
class GlobalSampler:
@classmethod
def INPUT_TYPES(s):
@@ -993,6 +1024,7 @@ NODE_CLASS_MAPPINGS = {
"ZipPrompt //Inspire": ZipPrompt,
"PromptExtractor //Inspire": PromptExtractor,
"GlobalSeed //Inspire": GlobalSeed,
"SeedLogger //Inspire": SeedLogger,
"GlobalSampler //Inspire": GlobalSampler,
"BindImageListPromptList //Inspire": BindImageListPromptList,
"WildcardEncode //Inspire": WildcardEncodeInspire,
@@ -1004,7 +1036,7 @@ NODE_CLASS_MAPPINGS = {
"MakeBasicPipe //Inspire": MakeBasicPipe,
"RemoveControlNet //Inspire": RemoveControlNet,
"RemoveControlNetFromRegionalPrompts //Inspire": RemoveControlNetFromRegionalPrompts,
"CompositeNoise //Inspire": CompositeNoise
"CompositeNoise //Inspire": CompositeNoise,
}
NODE_DISPLAY_NAME_MAPPINGS = {
@@ -1015,6 +1047,7 @@ NODE_DISPLAY_NAME_MAPPINGS = {
"ZipPrompt //Inspire": "Zip Prompt (Inspire)",
"PromptExtractor //Inspire": "Prompt Extractor (Inspire)",
"GlobalSeed //Inspire": "Global Seed (Inspire)",
"SeedLogger //Inspire": "Seed Logger (Inspire)",
"GlobalSampler //Inspire": "Global Sampler (Inspire)",
"BindImageListPromptList //Inspire": "Bind [ImageList, PromptList] (Inspire)",
"WildcardEncode //Inspire": "Wildcard Encode (Inspire)",
+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.18"
version = "1.20"
license = { file = "LICENSE" }
dependencies = ["matplotlib", "cachetools"]
+1 -1
View File
@@ -1,5 +1,5 @@
matplotlib
cachetools
numpy<2
numpy
webcolors
opencv-python