Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
690b0a0f61 | ||
|
|
84fbb3fa2e | ||
|
|
b2c7e06e79 | ||
|
|
a500aff476 |
@@ -1,7 +1,7 @@
|
|||||||
import configparser
|
import configparser
|
||||||
import os
|
import os
|
||||||
|
|
||||||
version_code = [7, 2, 1]
|
version_code = [7, 3, 2]
|
||||||
version = f"V{version_code[0]}.{version_code[1]}" + (f'.{version_code[2]}' if len(version_code) > 2 else '')
|
version = f"V{version_code[0]}.{version_code[1]}" + (f'.{version_code[2]}' if len(version_code) > 2 else '')
|
||||||
|
|
||||||
dependency_version = 22
|
dependency_version = 22
|
||||||
|
|||||||
@@ -78,6 +78,8 @@ class PreviewDetailerHookProvider:
|
|||||||
|
|
||||||
CATEGORY = "ImpactPack/Util"
|
CATEGORY = "ImpactPack/Util"
|
||||||
|
|
||||||
|
NOT_IDEMPOTENT = True
|
||||||
|
|
||||||
def doit(self, quality, unique_id):
|
def doit(self, quality, unique_id):
|
||||||
hook = hooks.PreviewDetailerHook(unique_id, quality)
|
hook = hooks.PreviewDetailerHook(unique_id, quality)
|
||||||
return (hook, hook)
|
return hook, hook
|
||||||
|
|||||||
@@ -238,11 +238,16 @@ class DetailerForEach:
|
|||||||
else:
|
else:
|
||||||
wmode, wildcard_chooser = None, None
|
wmode, wildcard_chooser = None, None
|
||||||
|
|
||||||
if wmode in ['ASC', 'DSC']:
|
if wmode in ['ASC', 'DSC', 'ASC-SIZE', 'DSC-SIZE']:
|
||||||
if wmode == 'ASC':
|
if wmode == 'ASC':
|
||||||
ordered_segs = sorted(segs[1], key=lambda x: (x.bbox[0], x.bbox[1]))
|
ordered_segs = sorted(segs[1], key=lambda x: (x.bbox[0], x.bbox[1]))
|
||||||
else:
|
elif wmode == 'DSC':
|
||||||
ordered_segs = sorted(segs[1], key=lambda x: (x.bbox[0], x.bbox[1]), reverse=True)
|
ordered_segs = sorted(segs[1], key=lambda x: (x.bbox[0], x.bbox[1]), reverse=True)
|
||||||
|
elif wmode == 'ASC-SIZE':
|
||||||
|
ordered_segs = sorted(segs[1], key=lambda x: (x.bbox[2]-x.bbox[0]) * (x.bbox[3]-x.bbox[1]))
|
||||||
|
|
||||||
|
else: # wmode == 'DSC-SIZE'
|
||||||
|
ordered_segs = sorted(segs[1], key=lambda x: (x.bbox[2]-x.bbox[0]) * (x.bbox[3]-x.bbox[1]), reverse=True)
|
||||||
else:
|
else:
|
||||||
ordered_segs = segs[1]
|
ordered_segs = segs[1]
|
||||||
|
|
||||||
@@ -291,6 +296,12 @@ class DetailerForEach:
|
|||||||
# Negative Conditioning is placeholder such as FLUX.1
|
# Negative Conditioning is placeholder such as FLUX.1
|
||||||
cropped_negative = negative
|
cropped_negative = negative
|
||||||
|
|
||||||
|
if wildcard_item and wildcard_item.strip() == '[SKIP]':
|
||||||
|
continue
|
||||||
|
|
||||||
|
if wildcard_item and wildcard_item.strip() == '[STOP]':
|
||||||
|
break
|
||||||
|
|
||||||
enhanced_image, cnet_pils = core.enhance_detail(cropped_image, model, clip, vae, guide_size, guide_size_for_bbox, max_size,
|
enhanced_image, cnet_pils = core.enhance_detail(cropped_image, model, clip, vae, guide_size, guide_size_for_bbox, max_size,
|
||||||
seg.bbox, seg_seed, steps, cfg, sampler_name, scheduler,
|
seg.bbox, seg_seed, steps, cfg, sampler_name, scheduler,
|
||||||
cropped_positive, cropped_negative, denoise, cropped_mask, force_inpaint,
|
cropped_positive, cropped_negative, denoise, cropped_mask, force_inpaint,
|
||||||
|
|||||||
+78
-60
@@ -10,7 +10,6 @@ import re
|
|||||||
import nodes
|
import nodes
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
|
|
||||||
class ImpactCompare:
|
class ImpactCompare:
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(cls):
|
def INPUT_TYPES(cls):
|
||||||
@@ -631,85 +630,104 @@ class ImpactControlBridge:
|
|||||||
def INPUT_TYPES(cls):
|
def INPUT_TYPES(cls):
|
||||||
return {"required": {
|
return {"required": {
|
||||||
"value": (any_typ,),
|
"value": (any_typ,),
|
||||||
"mode": ("BOOLEAN", {"default": True, "label_on": "Active", "label_off": "Mute/Bypass"}),
|
"mode": ("BOOLEAN", {"default": True, "label_on": "Active", "label_off": "Stop/Mute/Bypass"}),
|
||||||
"behavior": ("BOOLEAN", {"default": True, "label_on": "Mute", "label_off": "Bypass"}),
|
"behavior": (["Stop", "Mute", "Bypass"], ),
|
||||||
},
|
},
|
||||||
"hidden": {"unique_id": "UNIQUE_ID", "prompt": "PROMPT", "extra_pnginfo": "EXTRA_PNGINFO"}
|
"hidden": {"unique_id": "UNIQUE_ID", "prompt": "PROMPT", "extra_pnginfo": "EXTRA_PNGINFO"}
|
||||||
}
|
}
|
||||||
|
|
||||||
FUNCTION = "doit"
|
FUNCTION = "doit"
|
||||||
|
|
||||||
CATEGORY = "ImpactPack/Logic/_for_test"
|
CATEGORY = "ImpactPack/Logic"
|
||||||
RETURN_TYPES = (any_typ,)
|
RETURN_TYPES = (any_typ,)
|
||||||
RETURN_NAMES = ("value",)
|
RETURN_NAMES = ("value",)
|
||||||
OUTPUT_NODE = True
|
OUTPUT_NODE = True
|
||||||
|
|
||||||
|
DESCRIPTION = ("When behavior is Stop and mode is active, the input value is passed directly to the output.\n"
|
||||||
|
"When behavior is Mute/Bypass and mode is active, the node connected to the output is changed to active state.\n"
|
||||||
|
"When behavior is Stop and mode is Stop/Mute/Bypass, the workflow execution of the current node is halted.\n"
|
||||||
|
"When behavior is Mute/Bypass and mode is Stop/Mute/Bypass, the node connected to the output is changed to Mute/Bypass state.")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def IS_CHANGED(self, value, mode, behavior=True, unique_id=None, prompt=None, extra_pnginfo=None):
|
def IS_CHANGED(self, value, mode, behavior="Stop", unique_id=None, prompt=None, extra_pnginfo=None):
|
||||||
# NOTE: extra_pnginfo is not populated for IS_CHANGED.
|
if behavior == "Stop":
|
||||||
# so extra_pnginfo is useless in here
|
return value, mode, behavior
|
||||||
try:
|
else:
|
||||||
workflow = core.current_prompt['extra_data']['extra_pnginfo']['workflow']
|
# NOTE: extra_pnginfo is not populated for IS_CHANGED.
|
||||||
except:
|
# so extra_pnginfo is useless in here
|
||||||
print(f"[Impact Pack] core.current_prompt['extra_data']['extra_pnginfo']['workflow']")
|
try:
|
||||||
return 0
|
workflow = core.current_prompt['extra_data']['extra_pnginfo']['workflow']
|
||||||
|
except:
|
||||||
|
print(f"[Impact Pack] core.current_prompt['extra_data']['extra_pnginfo']['workflow']")
|
||||||
|
return 0
|
||||||
|
|
||||||
nodes, links = workflow_to_map(workflow)
|
nodes, links = workflow_to_map(workflow)
|
||||||
next_nodes = []
|
next_nodes = []
|
||||||
|
|
||||||
for link in nodes[unique_id]['outputs'][0]['links']:
|
for link in nodes[unique_id]['outputs'][0]['links']:
|
||||||
node_id = str(links[link][2])
|
node_id = str(links[link][2])
|
||||||
impact.utils.collect_non_reroute_nodes(nodes, links, next_nodes, node_id)
|
impact.utils.collect_non_reroute_nodes(nodes, links, next_nodes, node_id)
|
||||||
|
|
||||||
return next_nodes
|
return next_nodes
|
||||||
|
|
||||||
def doit(self, value, mode, behavior=True, unique_id=None, prompt=None, extra_pnginfo=None):
|
def doit(self, value, mode, behavior="Stop", unique_id=None, prompt=None, extra_pnginfo=None):
|
||||||
global error_skip_flag
|
global error_skip_flag
|
||||||
|
|
||||||
workflow_nodes, links = workflow_to_map(extra_pnginfo['workflow'])
|
if core.is_execution_model_version_supported:
|
||||||
|
from comfy_execution.graph import ExecutionBlocker
|
||||||
active_nodes = []
|
|
||||||
mute_nodes = []
|
|
||||||
bypass_nodes = []
|
|
||||||
|
|
||||||
for link in workflow_nodes[unique_id]['outputs'][0]['links']:
|
|
||||||
node_id = str(links[link][2])
|
|
||||||
|
|
||||||
next_nodes = []
|
|
||||||
impact.utils.collect_non_reroute_nodes(workflow_nodes, links, next_nodes, node_id)
|
|
||||||
|
|
||||||
for next_node_id in next_nodes:
|
|
||||||
node_mode = workflow_nodes[next_node_id]['mode']
|
|
||||||
|
|
||||||
if node_mode == 0:
|
|
||||||
active_nodes.append(next_node_id)
|
|
||||||
elif node_mode == 2:
|
|
||||||
mute_nodes.append(next_node_id)
|
|
||||||
elif node_mode == 4:
|
|
||||||
bypass_nodes.append(next_node_id)
|
|
||||||
|
|
||||||
if mode:
|
|
||||||
# active
|
|
||||||
should_be_active_nodes = mute_nodes + bypass_nodes
|
|
||||||
if len(should_be_active_nodes) > 0:
|
|
||||||
PromptServer.instance.send_sync("impact-bridge-continue", {"node_id": unique_id, 'actives': list(should_be_active_nodes)})
|
|
||||||
nodes.interrupt_processing()
|
|
||||||
|
|
||||||
elif behavior:
|
|
||||||
# mute
|
|
||||||
should_be_mute_nodes = active_nodes + bypass_nodes
|
|
||||||
if len(should_be_mute_nodes) > 0:
|
|
||||||
PromptServer.instance.send_sync("impact-bridge-continue", {"node_id": unique_id, 'mutes': list(should_be_mute_nodes)})
|
|
||||||
nodes.interrupt_processing()
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# bypass
|
print("[Impact Pack] ImpactControlBridge: ComfyUI is outdated. The 'Stop' behavior cannot function properly.")
|
||||||
should_be_bypass_nodes = active_nodes + mute_nodes
|
|
||||||
if len(should_be_bypass_nodes) > 0:
|
|
||||||
PromptServer.instance.send_sync("impact-bridge-continue", {"node_id": unique_id, 'bypasses': list(should_be_bypass_nodes)})
|
|
||||||
nodes.interrupt_processing()
|
|
||||||
|
|
||||||
return (value, )
|
if behavior == "Stop":
|
||||||
|
if mode:
|
||||||
|
return (value, )
|
||||||
|
else:
|
||||||
|
return (ExecutionBlocker(None), )
|
||||||
|
else:
|
||||||
|
workflow_nodes, links = workflow_to_map(extra_pnginfo['workflow'])
|
||||||
|
|
||||||
|
active_nodes = []
|
||||||
|
mute_nodes = []
|
||||||
|
bypass_nodes = []
|
||||||
|
|
||||||
|
for link in workflow_nodes[unique_id]['outputs'][0]['links']:
|
||||||
|
node_id = str(links[link][2])
|
||||||
|
|
||||||
|
next_nodes = []
|
||||||
|
impact.utils.collect_non_reroute_nodes(workflow_nodes, links, next_nodes, node_id)
|
||||||
|
|
||||||
|
for next_node_id in next_nodes:
|
||||||
|
node_mode = workflow_nodes[next_node_id]['mode']
|
||||||
|
|
||||||
|
if node_mode == 0:
|
||||||
|
active_nodes.append(next_node_id)
|
||||||
|
elif node_mode == 2:
|
||||||
|
mute_nodes.append(next_node_id)
|
||||||
|
elif node_mode == 4:
|
||||||
|
bypass_nodes.append(next_node_id)
|
||||||
|
|
||||||
|
if mode:
|
||||||
|
# active
|
||||||
|
should_be_active_nodes = mute_nodes + bypass_nodes
|
||||||
|
if len(should_be_active_nodes) > 0:
|
||||||
|
PromptServer.instance.send_sync("impact-bridge-continue", {"node_id": unique_id, 'actives': list(should_be_active_nodes)})
|
||||||
|
nodes.interrupt_processing()
|
||||||
|
|
||||||
|
elif behavior == "Mute" or behavior == True:
|
||||||
|
# mute
|
||||||
|
should_be_mute_nodes = active_nodes + bypass_nodes
|
||||||
|
if len(should_be_mute_nodes) > 0:
|
||||||
|
PromptServer.instance.send_sync("impact-bridge-continue", {"node_id": unique_id, 'mutes': list(should_be_mute_nodes)})
|
||||||
|
nodes.interrupt_processing()
|
||||||
|
|
||||||
|
else:
|
||||||
|
# bypass
|
||||||
|
should_be_bypass_nodes = active_nodes + mute_nodes
|
||||||
|
if len(should_be_bypass_nodes) > 0:
|
||||||
|
PromptServer.instance.send_sync("impact-bridge-continue", {"node_id": unique_id, 'bypasses': list(should_be_bypass_nodes)})
|
||||||
|
nodes.interrupt_processing()
|
||||||
|
|
||||||
|
return (value, )
|
||||||
|
|
||||||
|
|
||||||
class ImpactExecutionOrderController:
|
class ImpactExecutionOrderController:
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ from impact.utils import *
|
|||||||
from nodes import MAX_RESOLUTION
|
from nodes import MAX_RESOLUTION
|
||||||
import nodes
|
import nodes
|
||||||
from impact.impact_sampling import KSamplerWrapper, KSamplerAdvancedWrapper, separated_sample, impact_sample
|
from impact.impact_sampling import KSamplerWrapper, KSamplerAdvancedWrapper, separated_sample, impact_sample
|
||||||
|
import comfy
|
||||||
|
|
||||||
class TiledKSamplerProvider:
|
class TiledKSamplerProvider:
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -332,6 +332,10 @@ class RegionalSampler:
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def doit(seed, seed_2nd, seed_2nd_mode, steps, base_only_steps, denoise, samples, base_sampler, regional_prompts, overlap_factor, restore_latent,
|
def doit(seed, seed_2nd, seed_2nd_mode, steps, base_only_steps, denoise, samples, base_sampler, regional_prompts, overlap_factor, restore_latent,
|
||||||
additional_mode, additional_sampler, additional_sigma_ratio, unique_id=None):
|
additional_mode, additional_sampler, additional_sigma_ratio, unique_id=None):
|
||||||
|
|
||||||
|
samples = samples.copy()
|
||||||
|
samples['samples'] = comfy.sample.fix_empty_latent_channels(base_sampler.params[0], samples['samples'])
|
||||||
|
|
||||||
if restore_latent:
|
if restore_latent:
|
||||||
latent_compositor = nodes.NODE_CLASS_MAPPINGS['LatentCompositeMasked']()
|
latent_compositor = nodes.NODE_CLASS_MAPPINGS['LatentCompositeMasked']()
|
||||||
else:
|
else:
|
||||||
@@ -476,6 +480,9 @@ class RegionalSamplerAdvanced:
|
|||||||
def doit(add_noise, noise_seed, steps, start_at_step, end_at_step, overlap_factor, restore_latent, return_with_leftover_noise, latent_image, base_sampler, regional_prompts,
|
def doit(add_noise, noise_seed, steps, start_at_step, end_at_step, overlap_factor, restore_latent, return_with_leftover_noise, latent_image, base_sampler, regional_prompts,
|
||||||
additional_mode, additional_sampler, additional_sigma_ratio, unique_id):
|
additional_mode, additional_sampler, additional_sigma_ratio, unique_id):
|
||||||
|
|
||||||
|
new_latent_image = latent_image.copy()
|
||||||
|
new_latent_image['samples'] = comfy.sample.fix_empty_latent_channels(base_sampler.params[0], new_latent_image['samples'])
|
||||||
|
|
||||||
if restore_latent:
|
if restore_latent:
|
||||||
latent_compositor = nodes.NODE_CLASS_MAPPINGS['LatentCompositeMasked']()
|
latent_compositor = nodes.NODE_CLASS_MAPPINGS['LatentCompositeMasked']()
|
||||||
else:
|
else:
|
||||||
@@ -491,7 +498,6 @@ class RegionalSamplerAdvanced:
|
|||||||
end_at_step = min(steps, end_at_step)
|
end_at_step = min(steps, end_at_step)
|
||||||
total = (end_at_step - start_at_step) * region_len
|
total = (end_at_step - start_at_step) * region_len
|
||||||
|
|
||||||
new_latent_image = latent_image.copy()
|
|
||||||
base_latent_image = None
|
base_latent_image = None
|
||||||
region_masks = {}
|
region_masks = {}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
from impact.utils import any_typ, ByPassTypeTuple, make_3d_mask
|
from impact.utils import any_typ, ByPassTypeTuple, make_3d_mask
|
||||||
import comfy_extras.nodes_mask
|
import comfy_extras.nodes_mask
|
||||||
from comfy_execution.graph import ExecutionBlocker
|
|
||||||
from nodes import MAX_RESOLUTION
|
from nodes import MAX_RESOLUTION
|
||||||
import torch
|
import torch
|
||||||
import comfy
|
import comfy
|
||||||
@@ -166,6 +165,8 @@ class GeneralInversedSwitch:
|
|||||||
def doit(self, select, prompt, unique_id, input, **kwargs):
|
def doit(self, select, prompt, unique_id, input, **kwargs):
|
||||||
if core.is_execution_model_version_supported:
|
if core.is_execution_model_version_supported:
|
||||||
from comfy_execution.graph import ExecutionBlocker
|
from comfy_execution.graph import ExecutionBlocker
|
||||||
|
else:
|
||||||
|
print("[Impact Pack] InversedSwitch: ComfyUI is outdated. The 'select_on_execution' mode cannot function properly.")
|
||||||
|
|
||||||
res = []
|
res = []
|
||||||
|
|
||||||
|
|||||||
+15
-12
@@ -425,7 +425,7 @@ def process_with_loras(wildcard_opt, model, clip, clip_encoder=None, seed=None,
|
|||||||
|
|
||||||
def starts_with_regex(pattern, text):
|
def starts_with_regex(pattern, text):
|
||||||
regex = re.compile(pattern)
|
regex = re.compile(pattern)
|
||||||
return bool(regex.match(text))
|
return regex.match(text)
|
||||||
|
|
||||||
|
|
||||||
def split_to_dict(text):
|
def split_to_dict(text):
|
||||||
@@ -507,18 +507,21 @@ def process_wildcard_for_segs(wildcard):
|
|||||||
|
|
||||||
return 'LAB', WildcardChooserDict(items)
|
return 'LAB', WildcardChooserDict(items)
|
||||||
|
|
||||||
elif starts_with_regex(r"\[(ASC|DSC|RND)\]", wildcard):
|
|
||||||
mode = wildcard[1:4]
|
|
||||||
items = split_string_with_sep(wildcard[5:])
|
|
||||||
|
|
||||||
if mode == 'RND':
|
|
||||||
random.shuffle(items)
|
|
||||||
return mode, WildcardChooser(items, True)
|
|
||||||
else:
|
|
||||||
return mode, WildcardChooser(items, False)
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
return None, WildcardChooser([(None, wildcard)], False)
|
match = starts_with_regex(r"\[(ASC-SIZE|DSC-SIZE|ASC|DSC|RND)\]", wildcard)
|
||||||
|
|
||||||
|
if match:
|
||||||
|
mode = match[1]
|
||||||
|
items = split_string_with_sep(wildcard[len(match[0]):])
|
||||||
|
|
||||||
|
if mode == 'RND':
|
||||||
|
random.shuffle(items)
|
||||||
|
return mode, WildcardChooser(items, True)
|
||||||
|
else:
|
||||||
|
return mode, WildcardChooser(items, False)
|
||||||
|
|
||||||
|
else:
|
||||||
|
return None, WildcardChooser([(None, wildcard)], False)
|
||||||
|
|
||||||
|
|
||||||
def wildcard_load():
|
def wildcard_load():
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "comfyui-impact-pack"
|
name = "comfyui-impact-pack"
|
||||||
description = "This extension offers various detector nodes and detailer nodes that allow you to configure a workflow that automatically enhances facial details. And provide iterative upscaler."
|
description = "This extension offers various detector nodes and detailer nodes that allow you to configure a workflow that automatically enhances facial details. And provide iterative upscaler."
|
||||||
version = "7.2.1"
|
version = "7.3.2"
|
||||||
license = { file = "LICENSE.txt" }
|
license = { file = "LICENSE.txt" }
|
||||||
dependencies = ["segment-anything", "scikit-image", "piexif", "transformers", "opencv-python-headless", "GitPython", "scipy>=1.11.4"]
|
dependencies = ["segment-anything", "scikit-image", "piexif", "transformers", "opencv-python-headless", "GitPython", "scipy>=1.11.4"]
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user