Compare commits

...
20 Commits
Author SHA1 Message Date
Dr.Lt.Data 2346b67766 fixed: Switch (Any) - copy&paste error
https://github.com/ltdrdata/ComfyUI-Impact-Pack/issues/1012
2025-06-01 04:52:24 +09:00
Dr.Lt.Data 025db4b581 fixed: MaskRectArea - type error
https://github.com/ltdrdata/ComfyUI-Impact-Pack/issues/1001
2025-06-01 04:43:46 +09:00
Dr.Lt.Data f8e16df2be bump version 2025-05-19 08:33:30 +09:00
Dr.Lt.Data 7df60b2107 fixed: install.py - user friendly message with exception handling 2025-05-19 08:31:07 +09:00
Dr.Lt.Data b394c158ea modified: requirements.txt remove pinning <2 for numpy 2025-05-19 05:16:00 +09:00
Dr.Lt.Data 3e3cf3a5b4 support nunchaku lora loading in the wildcard feature
https://github.com/ltdrdata/ComfyUI-Impact-Pack/issues/993
2025-05-18 18:14:42 +09:00
Dr.Lt.Data 93fc248503 fixed: cannot connect wildcard input/output to the Switch / InversedSwitch nodes
https://github.com/ltdrdata/ComfyUI-Impact-Pack/issues/992
2025-05-16 04:42:26 +09:00
Dr.Lt.Data 16ffa7d462 hotfix: potential front error
```
TypeError: Cannot read properties of undefined (reading 'type')
```

https://github.com/ltdrdata/ComfyUI-Impact-Pack/issues/989
2025-05-16 03:59:10 +09:00
filtered cd34cfdd63 Fix empty widgets array throws in console (#988) 2025-05-03 14:37:31 +09:00
Dr.Lt.Data 38bb9ffdf6 fixed: Switch - buggy behavior on firefox browser
https://github.com/ltdrdata/ComfyUI-Impact-Pack/issues/983#issuecomment-2833471721
2025-04-28 00:54:31 +09:00
Dr.Lt.Data f939e66e1c fixed: this.widgets is undefined
https://github.com/ltdrdata/ComfyUI-Impact-Pack/issues/977
2025-04-27 22:16:11 +09:00
robo b22aa90cf4 allow for .yml files in wildcards (#966)
both are valid yaml extensions so it makes sense to allow both
2025-04-25 18:50:40 +09:00
Dr.Lt.Data d18aaecb93 bump version 2025-04-25 18:46:18 +09:00
だにえる a7840b4fbf feat: tensor_paste supports RGBA images with alpha channel blending (#962)
This enhancement adds support for properly handling RGBA images in the tensor_paste function.

The previous implementation caused errors when pasting images with alpha channels.
Now the function can handle all combinations of RGB and RGBA images:
- RGB to RGB (unchanged)
- RGBA to RGBA (with proper alpha compositing)
- RGB to RGBA
- RGBA to RGB

Fix for the error: "RuntimeError: The size of tensor a (4) must match the size of tensor b (3) at non-singleton dimension 3"
2025-04-25 18:35:03 +09:00
robo efa0cb66b2 always use impact.wildcards.process fixes server side wildcards.process not getting new wildcard_dict (#967) 2025-04-25 18:21:55 +09:00
Dr.Lt.Data 0b94005b1b hotfix: impactswitch - frontend crash
https://github.com/ltdrdata/ComfyUI-Impact-Pack/issues/970#issuecomment-2827153556
2025-04-25 08:03:20 +09:00
Dr.Lt.Data bfcb8674b3 feat: Select Nth Item (Any list)
https://github.com/ltdrdata/ComfyUI-Impact-Pack/issues/971
2025-04-24 18:00:37 +09:00
Dr.Lt.Data 839e5a9f90 fixed: ImpactSwitch - slot was not shrinked when disconnecting
fixed: ImpactSwitch - invalid upper bounding of the select value

https://github.com/ltdrdata/ComfyUI-Impact-Pack/issues/972
2025-04-24 12:38:35 +09:00
Dr.Lt.Data 5a2adda580 fixed: impact switch - compatibility patch with new front
https://github.com/ltdrdata/ComfyUI-Impact-Pack/issues/964
2025-04-22 02:06:08 +09:00
Dr.Lt.Data d05882a9e0 refactor: remove useless legacy code 2025-04-22 01:33:58 +09:00
14 changed files with 251 additions and 102 deletions
+1
View File
@@ -268,6 +268,7 @@ NOTE: The UltralyticsDetectorProvider node is not part of the ComfyUI-Impact-Pac
* `Masks to Mask List`, `Mask List to Masks`, `Make Mask List`, `Make Mask Batch` - It has the same functionality as the nodes above, but uses mask as input instead of image.
* `Flatten Mask Batch` - Flattens a Mask Batch into a single Mask. Normal operation is not guaranteed for non-binary masks.
* `Make List (Any)` - Create a list with arbitrary values.
* `Select Nth Item (Any list)` - Selects the Nth item from a list. If the index is out of range, it returns the last item in the list.
### Logics (experimental)
* These nodes are experimental nodes designed to implement the logic for loops and dynamic switching.
+2
View File
@@ -234,6 +234,7 @@ NODE_CLASS_MAPPINGS = {
"ImpactMakeAnyList": MakeAnyList,
"ImpactMakeMaskList": MakeMaskList,
"ImpactMakeMaskBatch": MakeMaskBatch,
"ImpactSelectNthItemOfAnyList": NthItemOfAnyList,
"RegionalSampler": RegionalSampler,
"RegionalSamplerAdvanced": RegionalSamplerAdvanced,
@@ -407,6 +408,7 @@ NODE_DISPLAY_NAME_MAPPINGS = {
"ImpactMakeMaskList": "Make Mask List",
"ImpactMakeMaskBatch": "Make Mask Batch",
"ImpactMakeAnyList": "Make List (Any)",
"ImpactSelectNthItemOfAnyList": "Select Nth Item (Any list)",
"ImpactStringSelector": "String Selector",
"StringListToString": "String List to String",
+14 -12
View File
@@ -68,7 +68,6 @@ def process_wrap(cmd_str, cwd=None, handler=None, env=None):
try:
import platform
from torchvision.datasets.utils import download_url
import impact.config
@@ -99,7 +98,7 @@ try:
if not os.path.exists(os.path.join(sam_path, "sam_vit_b_01ec64.pth")):
download_url("https://dl.fbaipublicfiles.com/segment_anything/sam_vit_b_01ec64.pth", sam_path)
except:
print(f"[Impact Pack] Failed to auto-download model files. Please download them manually.")
print("[Impact Pack] Failed to auto-download model files. Please download them manually.")
if not os.path.exists(onnx_path):
print(f"### ComfyUI-Impact-Pack: onnx model directory created ({onnx_path})")
@@ -108,18 +107,21 @@ try:
impact.config.write_config()
# Remove legacy subpack
subpack_path = os.path.join(os.path.dirname(__file__), 'impact_subpack')
if os.path.exists(subpack_path):
shutil.rmtree(subpack_path)
print(f"Legacy subpack is detected. '{subpack_path}' is removed.")
subpack_path = os.path.join(os.path.dirname(__file__), 'subpack')
if os.path.exists(subpack_path):
shutil.rmtree(subpack_path)
print(f"Legacy subpack is detected. '{subpack_path}' is removed.")
try:
subpack_path = os.path.join(os.path.dirname(__file__), 'impact_subpack')
if os.path.exists(subpack_path):
shutil.rmtree(subpack_path)
print(f"Legacy subpack is detected. '{subpack_path}' is removed.")
subpack_path = os.path.join(os.path.dirname(__file__), 'subpack')
if os.path.exists(subpack_path):
shutil.rmtree(subpack_path)
print(f"Legacy subpack is detected. '{subpack_path}' is removed.")
except:
print(f"ERROT: Failed to delete legacy subpack '{subpack_path}'\nPlease delete the folder after terminate ComfyUI.")
install()
except Exception as e:
except Exception:
print("[ERROR] ComfyUI-Impact-Pack: Dependency installation has failed. Please install manually.")
traceback.print_exc()
+42
View File
@@ -3,6 +3,48 @@ import { app } from "../../scripts/app.js";
let original_show = app.ui.dialog.show;
export function customAlert(message) {
try {
app.extensionManager.toast.addAlert(message);
}
catch {
alert(message);
}
}
export function isBeforeFrontendVersion(compareVersion) {
try {
const frontendVersion = window['__COMFYUI_FRONTEND_VERSION__'];
if (typeof frontendVersion !== 'string') {
return false;
}
function parseVersion(versionString) {
const parts = versionString.split('.').map(Number);
return parts.length === 3 && parts.every(part => !isNaN(part)) ? parts : null;
}
const currentVersion = parseVersion(frontendVersion);
const comparisonVersion = parseVersion(compareVersion);
if (!currentVersion || !comparisonVersion) {
return false;
}
for (let i = 0; i < 3; i++) {
if (currentVersion[i] > comparisonVersion[i]) {
return false;
} else if (currentVersion[i] < comparisonVersion[i]) {
return true;
}
}
return false;
} catch {
return true;
}
}
function dialog_show_wrapper(html) {
if (typeof html === "string") {
if(html.includes("IMPACT-PACK-SIGNAL: STOP CONTROL BRIDGE")) {
+71 -28
View File
@@ -1,6 +1,13 @@
import { ComfyApp, app } from "../../scripts/app.js";
import { ComfyDialog, $el } from "../../scripts/ui.js";
import { api } from "../../scripts/api.js";
import { customAlert, isBeforeFrontendVersion } from "./common.js";
const is_legacy_front = () => isBeforeFrontendVersion('1.16.9');
if(is_legacy_front()) {
customAlert("An outdated version(<1.16.9) of the `comfyui-frontend-package` is installed. It is not compatible with the current version of the Impact Pack.");
}
let wildcards_list = [];
async function load_wildcards() {
@@ -324,6 +331,32 @@ app.registerExtension({
}
}
if(nodeData.name == "ImpactSelectNthItemOfAnyList") {
const onConnectionsChange = nodeType.prototype.onConnectionsChange;
nodeType.prototype.onConnectionsChange = function (type, index, connected, link_info) {
if(!link_info || this.inputs[0].type != '*')
return;
if(index >= 2)
return;
// assign type
let slot_type = '*';
if(type == 2) {
slot_type = link_info.type;
}
else {
const node = app.graph.getNodeById(link_info.origin_id);
slot_type = node.outputs[link_info.origin_slot].type;
}
this.inputs[0].type = slot_type;
this.outputs[0].type = slot_type;
this.outputs[0].label = slot_type;
}
}
if(nodeData.name === 'ImpactInversedSwitch') {
nodeData.output = ['*'];
nodeData.output_is_list = [false];
@@ -337,12 +370,12 @@ app.registerExtension({
if(type == 2) {
// connect output
if(connected){
if(app.graph._nodes_by_id[link_info.target_id].type == 'Reroute') {
if(app.graph._nodes_by_id[link_info.target_id]?.type == 'Reroute') {
app.graph._nodes_by_id[link_info.target_id].disconnectInput(link_info.target_slot);
}
if(this.outputs[0].type == '*'){
if(link_info.type == '*') {
if(link_info.type == '*' && app.graph.getNodeById(link_info.target_id).slots[link_info.target_slot].type != '*') {
app.graph._nodes_by_id[link_info.target_id].disconnectInput(link_info.target_slot);
}
else {
@@ -359,7 +392,7 @@ app.registerExtension({
}
}
else {
if(app.graph._nodes_by_id[link_info.origin_id].type == 'Reroute')
if(app.graph._nodes_by_id[link_info.origin_id]?.type == 'Reroute')
this.disconnectInput(link_info.target_slot);
// connect input
@@ -371,7 +404,7 @@ app.registerExtension({
return; // fallback
}
if(origin_type == '*') {
if(origin_type == '*' && app.graph.getNodeById(link_info.origin_id).slots[link_info.origin_slot].type != '*') {
this.disconnectInput(link_info.target_slot);
return;
}
@@ -395,8 +428,9 @@ app.registerExtension({
!stackTrace.includes('LGraphNode.prototype.connect') && // for touch device
!stackTrace.includes('LGraphNode.connect') && // for mouse device
!stackTrace.includes('loadGraphData')) {
if(this.outputs[link_info.origin_slot].links.length == 0)
if(this.outputs[link_info.origin_slot].links.length == 0) {
this.removeOutput(link_info.origin_slot);
}
}
}
@@ -409,9 +443,12 @@ app.registerExtension({
slot_i++;
}
let last_slot = this.outputs[this.outputs.length - 1];
if (last_slot.slot_index == link_info.origin_slot) {
this.addOutput(`output${slot_i}`, this.outputs[0].type);
if(connected) {
// NOTE: node.slot_index is different with link_info.origin_slot
let last_slot_index = this.outputs.length - 1;
if (last_slot_index == link_info.origin_slot) {
this.addOutput(`output${slot_i}`, this.outputs[0].type);
}
}
let select_slot = this.inputs.find(x => x.name == "select");
@@ -474,6 +511,23 @@ app.registerExtension({
const onConnectionsChange = nodeType.prototype.onConnectionsChange;
nodeType.prototype.onConnectionsChange = function (type, index, connected, link_info) {
const stackTrace = new Error().stack;
if(stackTrace.includes('loadGraphData')) {
if(this.widgets?.[0]) {
this.widgets[0].options.max = this.inputs.length-3;
this.widgets[0].value = Math.min(this.widgets[0].value, this.widgets[0].options.max);
}
return;
}
if(stackTrace.includes('pasteFromClipboard')) {
if(this.widgets?.[0]) {
this.widgets[0].options.max = this.inputs.length-3;
this.widgets[0].value = Math.min(this.widgets[0].value, this.widgets[0].options.max);
}
return;
}
if(!link_info)
return;
@@ -485,7 +539,7 @@ app.registerExtension({
}
if(this.outputs[0].type == '*'){
if(link_info.type == '*') {
if(link_info.type == '*' && app.graph.getNodeById(link_info.target_id).slots[link_info.target_slot].type != '*') {
app.graph._nodes_by_id[link_info.target_id].disconnectInput(link_info.target_slot);
}
else {
@@ -516,12 +570,12 @@ app.registerExtension({
if(this.inputs[0].type == '*'){
const node = app.graph.getNodeById(link_info.origin_id);
let origin_type = node.outputs[link_info.origin_slot]?.type;
if(link_info.target_slot == 0 && this.inputs.length > 1) {
if(link_info.target_slot == 0 && this.inputs.length > 3) { // NOTE: widgets are regarded as input since new front
origin_type = this.inputs[1].type;
node.connect(link_info.origin_slot, node.id, 'input1');
}
if(origin_type == '*') {
if(origin_type == '*' && app.graph.getNodeById(link_info.origin_id).slots[link_info.origin_slot].type != '*') {
this.disconnectInput(link_info.target_slot);
return;
}
@@ -539,15 +593,8 @@ app.registerExtension({
}
let select_slot = this.inputs.find(x => x.name == "select");
let mode_slot = this.inputs.find(x => x.name == "sel_mode");
let converted_count = 0;
converted_count += select_slot?1:0;
converted_count += mode_slot?1:0;
if (!connected && (this.inputs.length > 1+converted_count)) {
const stackTrace = new Error().stack;
if (!connected && (this.inputs.length > 3)) {
if(
!stackTrace.includes('LGraphNode.prototype.connect') && // for touch device
!stackTrace.includes('LGraphNode.connect') && // for mouse device
@@ -557,6 +604,7 @@ app.registerExtension({
}
}
let slot_i = 1;
for (let i = 0; i < this.inputs.length; i++) {
let input_i = this.inputs[i];
@@ -566,18 +614,13 @@ app.registerExtension({
}
}
let last_slot = this.inputs[this.inputs.length - 1];
if (
(last_slot.name == 'select' && last_slot.name != 'sel_mode' && this.inputs[this.inputs.length - 2].link != undefined)
|| (last_slot.name != 'select' && last_slot.name != 'sel_mode' && last_slot.link != undefined)) {
this.addInput(`${input_name}${slot_i}`, this.outputs[0].type);
if(connected) {
this.addInput(`${input_name}${slot_i}`, this.outputs[0].type);
}
if(this.widgets?.length) {
this.widgets[0].options.max = select_slot?this.inputs.length-1:this.inputs.length;
if(this.widgets?.[0]) {
this.widgets[0].options.max = this.inputs.length-3;
this.widgets[0].value = Math.min(this.widgets[0].value, this.widgets[0].options.max);
if(this.widgets[0].options.max > 0 && this.widgets[0].value == 0)
this.widgets[0].value = 1;
}
}
}
+1 -1
View File
@@ -1,7 +1,7 @@
import configparser
import os
version_code = [8, 11]
version_code = [8, 15, 3]
version = f"V{version_code[0]}.{version_code[1]}" + (f'.{version_code[2]}' if len(version_code) > 2 else '')
dependency_version = 24
+1 -1
View File
@@ -1906,7 +1906,7 @@ class MaskRectArea:
# search for node
node_found = False
for node in extra_pnginfo["workflow"]["nodes"]:
if node["id"] == int(unique_id):
if str(node["id"]) == unique_id:
min_x = node["properties"].get("x", 0) / 100
min_y = node["properties"].get("y", 0) / 100
width = node["properties"].get("w", 0) / 100
+2 -3
View File
@@ -17,7 +17,6 @@ import numpy as np
import nodes
from PIL import Image
import io
import impact.wildcards as wildcards
import comfy
from io import BytesIO
import random
@@ -183,7 +182,7 @@ async def wildcards_list(request):
@PromptServer.instance.routes.post("/impact/wildcards")
async def populate_wildcards(request):
data = await request.json()
populated = wildcards.process(data['text'], data.get('seed', None))
populated = impact.wildcards.process(data['text'], data.get('seed', None))
return web.json_response({"text": populated})
@@ -512,7 +511,7 @@ def onprompt_populate_wildcards(json_data):
else:
input_seed = int(inputs['seed'])
inputs['populated_text'] = wildcards.process(inputs['wildcard_text'], input_seed)
inputs['populated_text'] = impact.wildcards.process(inputs['wildcard_text'], input_seed)
inputs['mode'] = 'reproduce'
PromptServer.instance.send_sync("impact-node-feedback", {"node_id": k, "widget_name": "populated_text", "type": "STRING", "value": inputs['populated_text']})
+1 -22
View File
@@ -8,7 +8,7 @@ from impact.utils import any_typ
import impact.core as core
import re
import nodes
import traceback
class ImpactCompare:
@classmethod
@@ -574,27 +574,6 @@ class ImpactSleep:
return (signal,)
error_skip_flag = False
try:
import cm_global
def filter_message(str):
global error_skip_flag
if "IMPACT-PACK-SIGNAL: STOP CONTROL BRIDGE" in str:
return True
elif error_skip_flag and "ERROR:root:!!! Exception during processing !!!\n" == str:
error_skip_flag = False
return True
else:
return False
cm_global.try_call(api='cm.register_message_collapse', f=filter_message)
except Exception as e:
print(f"[WARN] ComfyUI-Impact-Pack: `ComfyUI` or `ComfyUI-Manager` is an outdated version.")
pass
def workflow_to_map(workflow):
nodes = {}
links = {}
+25
View File
@@ -446,6 +446,31 @@ class MakeMaskList:
return (masks, )
class NthItemOfAnyList:
@classmethod
def INPUT_TYPES(s):
return {"required": {
"any_list": (any_typ,),
"index": ("INT", {"default": 0, "min": 0, "max": sys.maxsize, "step": 1, "tooltip": "The index of the item you want to select from the list."}),
}
}
RETURN_TYPES = (any_typ,)
INPUT_IS_LIST = True
FUNCTION = "doit"
CATEGORY = "ImpactPack/Util"
DESCRIPTION = "Selects the Nth item from a list. If the index is out of range, it returns the last item in the list."
def doit(self, any_list, index):
i = index[0]
if i >= len(any_list):
return (any_list[-1],)
else:
return (any_list[i],)
class MakeImageList:
@classmethod
def INPUT_TYPES(s):
+53 -13
View File
@@ -178,31 +178,71 @@ def tensor2numpy(image):
def tensor_paste(image1, image2, left_top, mask):
"""Mask and image2 has to be the same size"""
"""
Pastes image2 onto image1 at position left_top using mask.
Supports both RGB and RGBA images.
"""
_tensor_check_image(image1)
_tensor_check_image(image2)
_tensor_check_mask(mask)
if image2.shape[1:3] != mask.shape[1:3]:
mask = resize_mask(mask.squeeze(dim=3), image2.shape[1:3]).unsqueeze(dim=3)
# raise ValueError(f"Inconsistent size: Image ({image2.shape[1:3]}) != Mask ({mask.shape[1:3]})")
x, y = left_top
_, h1, w1, _ = image1.shape
_, h2, w2, _ = image2.shape
# calculate image patch size
_, h1, w1, c1 = image1.shape
_, h2, w2, c2 = image2.shape
# Calculate image patch size
w = min(w1, x + w2) - x
h = min(h1, y + h2) - y
# If the patch is out of bound, nothing to do!
if w <= 0 or h <= 0:
return
mask = mask[:, :h, :w, :]
image1[:, y:y+h, x:x+w, :] = (
(1 - mask) * image1[:, y:y+h, x:x+w, :] +
mask * image2[:, :h, :w, :]
)
# Get the region to be modified
region1 = image1[:, y:y+h, x:x+w, :]
region2 = image2[:, :h, :w, :]
# Handle RGB and RGBA cases
if c1 == 3 and c2 == 3:
# Both RGB - simple case
image1[:, y:y+h, x:x+w, :] = (1 - mask) * region1 + mask * region2
elif c1 == 4 and c2 == 4:
# Both RGBA - need to handle alpha channel separately
# RGB channels
image1[:, y:y+h, x:x+w, :3] = (
(1 - mask) * region1[:, :, :, :3] +
mask * region2[:, :, :, :3]
)
# Alpha channel - use "over" composition
a1 = region1[:, :, :, 3:4]
a2 = region2[:, :, :, 3:4] * mask
new_alpha = a1 + a2 * (1 - a1)
image1[:, y:y+h, x:x+w, 3:4] = new_alpha
elif c1 == 4 and c2 == 3:
# Target is RGBA, source is RGB - assume source is fully opaque
image1[:, y:y+h, x:x+w, :3] = (
(1 - mask) * region1[:, :, :, :3] +
mask * region2
)
# Alpha channel - reduce alpha where mask is applied
image1[:, y:y+h, x:x+w, 3:4] = region1[:, :, :, 3:4] * (1 - mask) + mask
elif c1 == 3 and c2 == 4:
# Target is RGB, source is RGBA - apply source alpha to mask
effective_mask = mask * region2[:, :, :, 3:4]
image1[:, y:y+h, x:x+w, :] = (
(1 - effective_mask) * region1 +
effective_mask * region2[:, :, :, :3]
)
return
+36 -20
View File
@@ -8,6 +8,7 @@ import numpy as np
import threading
from impact import utils
from impact import config
import logging
wildcards_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "wildcards"))
@@ -65,7 +66,7 @@ def read_wildcard_dict(wildcard_path):
with open(file_path, 'r', encoding="UTF-8", errors="ignore") as f:
lines = f.read().splitlines()
wildcard_dict[key] = [x for x in lines if not x.strip().startswith('#')]
elif file.endswith('.yaml'):
elif file.endswith('.yaml') or file.endswith('.yml'):
file_path = os.path.join(root, file)
try:
@@ -358,6 +359,7 @@ def extract_lora_values(string):
lbw = None
lbw_a = None
lbw_b = None
loader = None
if len(item) > 0:
lora = item[0]
@@ -376,6 +378,8 @@ def extract_lora_values(string):
lbw_b = safe_float(lbw_item[2:].strip())
elif lbw_item.strip() != '':
lbw = lbw_item
elif sub_item.startswith("LOADER="):
loader = sub_item[7:]
if a is None:
a = 1.0
@@ -383,7 +387,7 @@ def extract_lora_values(string):
b = a
if lora is not None and lora not in added:
result.append((lora, a, b, lbw, lbw_a, lbw_b))
result.append((lora, a, b, lbw, lbw_a, lbw_b, loader))
added.add(lora)
return result
@@ -407,6 +411,8 @@ def resolve_lora_name(lora_name_cache, name):
if x.endswith(name):
return x
return None
def process_with_loras(wildcard_opt, model, clip, clip_encoder=None, seed=None, processed=None):
"""
@@ -427,7 +433,7 @@ def process_with_loras(wildcard_opt, model, clip, clip_encoder=None, seed=None,
loras = extract_lora_values(pass1)
pass2 = remove_lora_tags(pass1)
for lora_name, model_weight, clip_weight, lbw, lbw_a, lbw_b in loras:
for lora_name, model_weight, clip_weight, lbw, lbw_a, lbw_b, loader in loras:
lora_name_ext = lora_name.split('.')
if ('.'+lora_name_ext[-1]) not in folder_paths.supported_pt_extensions:
lora_name = lora_name+".safetensors"
@@ -441,26 +447,36 @@ def process_with_loras(wildcard_opt, model, clip, clip_encoder=None, seed=None,
path = None
if path is not None:
print(f"LOAD LORA: {lora_name}: {model_weight}, {clip_weight}, LBW={lbw}, A={lbw_a}, B={lbw_b}")
logging.info(f"LOAD LORA: {lora_name}: {model_weight}, {clip_weight}, LBW={lbw}, A={lbw_a}, B={lbw_b}, LOADER={loader}")
def default_lora():
return nodes.LoraLoader().load_lora(model, clip, lora_name, model_weight, clip_weight)
if lbw is not None:
if 'LoraLoaderBlockWeight //Inspire' not in nodes.NODE_CLASS_MAPPINGS:
utils.try_install_custom_node(
'https://github.com/ltdrdata/ComfyUI-Inspire-Pack',
"To use 'LBW=' syntax in wildcards, 'Inspire Pack' extension is required.")
print(f"'LBW(Lora Block Weight)' is given, but the 'Inspire Pack' is not installed. The LBW= attribute is being ignored.")
model, clip = default_lora()
if loader is not None:
if loader == 'nunchaku':
if 'NunchakuFluxLoraLoader' not in nodes.NODE_CLASS_MAPPINGS:
logging.warning(f"To use `LOADER=nunchaku`, 'ComfyUI-nunchaku' is required. The LOADER= attribute is being ignored.")
cls = nodes.NODE_CLASS_MAPPINGS['NunchakuFluxLoraLoader']
model = cls().load_lora(model, lora_name, model_weight)[0]
else:
cls = nodes.NODE_CLASS_MAPPINGS['LoraLoaderBlockWeight //Inspire']
model, clip, _ = cls().doit(model, clip, lora_name, model_weight, clip_weight, False, 0, lbw_a, lbw_b, "", lbw)
logging.warning(f"LORA LOADER NOT FOUND: '{loader}'")
else:
model, clip = default_lora()
def default_lora():
return nodes.LoraLoader().load_lora(model, clip, lora_name, model_weight, clip_weight)
if lbw is not None:
if 'LoraLoaderBlockWeight //Inspire' not in nodes.NODE_CLASS_MAPPINGS:
utils.try_install_custom_node(
'https://github.com/ltdrdata/ComfyUI-Inspire-Pack',
"To use 'LBW=' syntax in wildcards, 'Inspire Pack' extension is required.")
logging.warning(f"'LBW(Lora Block Weight)' is given, but the 'Inspire Pack' is not installed. The LBW= attribute is being ignored.")
model, clip = default_lora()
else:
cls = nodes.NODE_CLASS_MAPPINGS['LoraLoaderBlockWeight //Inspire']
model, clip, _ = cls().doit(model, clip, lora_name, model_weight, clip_weight, False, 0, lbw_a, lbw_b, "", lbw)
else:
model, clip = default_lora()
else:
print(f"LORA NOT FOUND: {orig_lora_name}")
logging.warning(f"LORA NOT FOUND: {orig_lora_name}")
pass3 = [x.strip() for x in pass2.split("BREAK")]
pass3 = [x for x in pass3 if x != '']
@@ -469,7 +485,7 @@ def process_with_loras(wildcard_opt, model, clip, clip_encoder=None, seed=None,
pass3 = ['']
pass3_str = [f'[{x}]' for x in pass3]
print(f"CLIP: {str.join(' + ', pass3_str)}")
logging.info(f"CLIP: {str.join(' + ', pass3_str)}")
result = None
+1 -1
View File
@@ -1,7 +1,7 @@
[project]
name = "comfyui-impact-pack"
description = "This node pack offers various detector nodes and detailer nodes that allow you to configure a workflow that automatically enhances facial details. And provide iterative upscaler."
version = "8.11"
version = "8.15.3"
license = { file = "LICENSE.txt" }
dependencies = ["segment-anything", "scikit-image", "piexif", "transformers", "opencv-python-headless", "GitPython", "scipy>=1.11.4"]
+1 -1
View File
@@ -4,6 +4,6 @@ piexif
transformers
opencv-python-headless
scipy>=1.11.4
numpy<2
numpy
dill
matplotlib