|
import sys |
|
import time |
|
|
|
import execution |
|
import folder_paths |
|
import impact.impact_server |
|
from server import PromptServer |
|
from impact.utils import any_typ |
|
import impact.core as core |
|
|
|
|
|
class ImpactCompare: |
|
@classmethod |
|
def INPUT_TYPES(cls): |
|
return { |
|
"required": { |
|
"cmp": (['a = b', 'a <> b', 'a > b', 'a < b', 'a >= b', 'a <= b', 'tt', 'ff'],), |
|
"a": (any_typ, ), |
|
"b": (any_typ, ), |
|
}, |
|
} |
|
|
|
FUNCTION = "doit" |
|
CATEGORY = "ImpactPack/Logic" |
|
|
|
RETURN_TYPES = ("BOOLEAN", ) |
|
|
|
def doit(self, cmp, a, b): |
|
if cmp == "a = b": |
|
return (a == b, ) |
|
elif cmp == "a <> b": |
|
return (a != b, ) |
|
elif cmp == "a > b": |
|
return (a > b, ) |
|
elif cmp == "a < b": |
|
return (a < b, ) |
|
elif cmp == "a >= b": |
|
return (a >= b, ) |
|
elif cmp == "a <= b": |
|
return (a <= b, ) |
|
elif cmp == 'tt': |
|
return (True, ) |
|
else: |
|
return (False, ) |
|
|
|
|
|
class ImpactNotEmptySEGS: |
|
@classmethod |
|
def INPUT_TYPES(cls): |
|
return {"required": {"segs": ("SEGS",)}} |
|
|
|
FUNCTION = "doit" |
|
CATEGORY = "ImpactPack/Logic" |
|
|
|
RETURN_TYPES = ("BOOLEAN", ) |
|
|
|
def doit(self, segs): |
|
return (segs[1] != [], ) |
|
|
|
|
|
class ImpactConditionalBranch: |
|
@classmethod |
|
def INPUT_TYPES(cls): |
|
return { |
|
"required": { |
|
"cond": ("BOOLEAN", {"forceInput": True}), |
|
"tt_value": (any_typ,), |
|
"ff_value": (any_typ,), |
|
}, |
|
} |
|
|
|
FUNCTION = "doit" |
|
CATEGORY = "ImpactPack/Logic" |
|
|
|
RETURN_TYPES = (any_typ, ) |
|
|
|
def doit(self, cond, tt_value, ff_value): |
|
if cond: |
|
return (tt_value,) |
|
else: |
|
return (ff_value,) |
|
|
|
|
|
class ImpactConditionalStopIteration: |
|
@classmethod |
|
def INPUT_TYPES(cls): |
|
return { |
|
"required": { "cond": ("BOOLEAN", {"forceInput": True}), }, |
|
} |
|
|
|
FUNCTION = "doit" |
|
CATEGORY = "ImpactPack/Logic" |
|
|
|
RETURN_TYPES = () |
|
|
|
OUTPUT_NODE = True |
|
|
|
def doit(self, cond): |
|
if cond: |
|
PromptServer.instance.send_sync("stop-iteration", {}) |
|
return {} |
|
|
|
|
|
class ImpactNeg: |
|
@classmethod |
|
def INPUT_TYPES(cls): |
|
return { |
|
"required": { "value": ("BOOLEAN", {"forceInput": True}), }, |
|
} |
|
|
|
FUNCTION = "doit" |
|
CATEGORY = "ImpactPack/Logic" |
|
|
|
RETURN_TYPES = ("BOOLEAN", ) |
|
|
|
def doit(self, value): |
|
return (not value, ) |
|
|
|
|
|
class ImpactInt: |
|
@classmethod |
|
def INPUT_TYPES(cls): |
|
return { |
|
"required": { |
|
"value": ("INT", {"default": 0, "min": 0, "max": sys.maxsize, "step": 1}), |
|
}, |
|
} |
|
|
|
FUNCTION = "doit" |
|
CATEGORY = "ImpactPack/Logic" |
|
|
|
RETURN_TYPES = ("INT", ) |
|
|
|
def doit(self, value): |
|
return (value, ) |
|
|
|
|
|
class ImpactFloat: |
|
@classmethod |
|
def INPUT_TYPES(cls): |
|
return { |
|
"required": { |
|
"value": ("FLOAT", {"default": 1.0, "min": -3.402823466e+38, "max": 3.402823466e+38}), |
|
}, |
|
} |
|
|
|
FUNCTION = "doit" |
|
CATEGORY = "ImpactPack/Logic" |
|
|
|
RETURN_TYPES = ("FLOAT", ) |
|
|
|
def doit(self, value): |
|
return (value, ) |
|
|
|
|
|
class ImpactValueSender: |
|
@classmethod |
|
def INPUT_TYPES(cls): |
|
return {"required": { |
|
"value": (any_typ, ), |
|
"link_id": ("INT", {"default": 0, "min": 0, "max": sys.maxsize, "step": 1}), |
|
}, |
|
"optional": { |
|
"signal_opt": (any_typ,), |
|
} |
|
} |
|
|
|
OUTPUT_NODE = True |
|
|
|
FUNCTION = "doit" |
|
|
|
CATEGORY = "ImpactPack/Logic" |
|
|
|
RETURN_TYPES = (any_typ, ) |
|
RETURN_NAMES = ("signal", ) |
|
|
|
def doit(self, value, link_id=0, signal_opt=None): |
|
PromptServer.instance.send_sync("value-send", {"link_id": link_id, "value": value}) |
|
return (signal_opt, ) |
|
|
|
|
|
class ImpactIntConstSender: |
|
@classmethod |
|
def INPUT_TYPES(cls): |
|
return {"required": { |
|
"signal": (any_typ, ), |
|
"value": ("INT", {"default": 0, "min": 0, "max": sys.maxsize, "step": 1}), |
|
"link_id": ("INT", {"default": 0, "min": 0, "max": sys.maxsize, "step": 1}), |
|
}, |
|
} |
|
|
|
OUTPUT_NODE = True |
|
|
|
FUNCTION = "doit" |
|
|
|
CATEGORY = "ImpactPack/Logic" |
|
|
|
RETURN_TYPES = () |
|
|
|
def doit(self, signal, value, link_id=0): |
|
PromptServer.instance.send_sync("value-send", {"link_id": link_id, "value": value}) |
|
return {} |
|
|
|
|
|
class ImpactValueReceiver: |
|
@classmethod |
|
def INPUT_TYPES(cls): |
|
return {"required": { |
|
"typ": (["STRING", "INT", "FLOAT", "BOOLEAN"], ), |
|
"value": ("STRING", {"default": ""}), |
|
"link_id": ("INT", {"default": 0, "min": 0, "max": sys.maxsize, "step": 1}), |
|
}, |
|
} |
|
|
|
FUNCTION = "doit" |
|
|
|
CATEGORY = "ImpactPack/Logic" |
|
|
|
RETURN_TYPES = (any_typ, ) |
|
|
|
def doit(self, typ, value, link_id=0): |
|
if typ == "INT": |
|
return (int(value), ) |
|
elif typ == "FLOAT": |
|
return (float(value), ) |
|
elif typ == "BOOLEAN": |
|
return (bool(value), ) |
|
else: |
|
return (value, ) |
|
|
|
|
|
class ImpactImageInfo: |
|
@classmethod |
|
def INPUT_TYPES(cls): |
|
return {"required": { |
|
"value": ("IMAGE", ), |
|
}, |
|
} |
|
|
|
FUNCTION = "doit" |
|
|
|
CATEGORY = "ImpactPack/Logic/_for_test" |
|
|
|
RETURN_TYPES = ("INT", "INT", "INT", "INT") |
|
RETURN_NAMES = ("batch", "height", "width", "channel") |
|
|
|
def doit(self, value): |
|
return (value.shape[0], value.shape[1], value.shape[2], value.shape[3]) |
|
|
|
|
|
class ImpactMinMax: |
|
@classmethod |
|
def INPUT_TYPES(cls): |
|
return {"required": { |
|
"mode": ("BOOLEAN", {"default": True, "label_on": "max", "label_off": "min"}), |
|
"a": (any_typ,), |
|
"b": (any_typ,), |
|
}, |
|
} |
|
|
|
FUNCTION = "doit" |
|
|
|
CATEGORY = "ImpactPack/Logic/_for_test" |
|
|
|
RETURN_TYPES = ("INT", ) |
|
|
|
def doit(self, mode, a, b): |
|
if mode: |
|
return (max(a, b), ) |
|
else: |
|
return (min(a, b),) |
|
|
|
|
|
class ImpactQueueTrigger: |
|
@classmethod |
|
def INPUT_TYPES(cls): |
|
return {"required": { |
|
"signal": (any_typ,), |
|
"mode": ("BOOLEAN", {"default": True, "label_on": "Trigger", "label_off": "Don't trigger"}), |
|
} |
|
} |
|
|
|
FUNCTION = "doit" |
|
|
|
CATEGORY = "ImpactPack/Logic/_for_test" |
|
RETURN_TYPES = (any_typ,) |
|
RETURN_NAMES = ("signal_opt",) |
|
OUTPUT_NODE = True |
|
|
|
def doit(self, signal, mode): |
|
if(mode): |
|
PromptServer.instance.send_sync("impact-add-queue", {}) |
|
|
|
return (signal,) |
|
|
|
|
|
class ImpactQueueTriggerCountdown: |
|
@classmethod |
|
def INPUT_TYPES(cls): |
|
return {"required": { |
|
"signal": (any_typ,), |
|
"count": ("INT", {"default": 10, "min": 0, "max": 0xffffffffffffffff}) |
|
}, |
|
"hidden": {"unique_id": "UNIQUE_ID"} |
|
} |
|
|
|
FUNCTION = "doit" |
|
|
|
CATEGORY = "ImpactPack/Logic/_for_test" |
|
RETURN_TYPES = (any_typ, "INT") |
|
RETURN_NAMES = ("signal_opt", "count") |
|
OUTPUT_NODE = True |
|
|
|
def doit(self, signal, count, unique_id): |
|
if count > 0: |
|
PromptServer.instance.send_sync("impact-node-feedback", |
|
{"node_id": unique_id, "widget_name": "count", "type": "int", "value": count-1}) |
|
PromptServer.instance.send_sync("impact-add-queue", {}) |
|
|
|
return (signal, count) |
|
|
|
|
|
class ImpactSetWidgetValue: |
|
@classmethod |
|
def INPUT_TYPES(cls): |
|
return {"required": { |
|
"signal": (any_typ,), |
|
"node_id": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}), |
|
"widget_name": ("STRING", {"multiline": False}), |
|
}, |
|
"optional": { |
|
"boolean_value": ("BOOLEAN", {"forceInput": True}), |
|
"int_value": ("INT", {"forceInput": True}), |
|
"float_value": ("FLOAT", {"forceInput": True}), |
|
"string_value": ("STRING", {"forceInput": True}), |
|
} |
|
} |
|
|
|
FUNCTION = "doit" |
|
|
|
CATEGORY = "ImpactPack/Logic/_for_test" |
|
RETURN_TYPES = (any_typ,) |
|
RETURN_NAMES = ("signal_opt",) |
|
OUTPUT_NODE = True |
|
|
|
def doit(self, signal, node_id, widget_name, boolean_value=None, int_value=None, float_value=None, string_value=None, ): |
|
kind = None |
|
if boolean_value is not None: |
|
value = boolean_value |
|
kind = "BOOLEAN" |
|
elif int_value is not None: |
|
value = int_value |
|
kind = "INT" |
|
elif float_value is not None: |
|
value = float_value |
|
kind = "FLOAT" |
|
elif string_value is not None: |
|
value = string_value |
|
kind = "STRING" |
|
else: |
|
value = None |
|
|
|
if value is not None: |
|
PromptServer.instance.send_sync("impact-node-feedback", |
|
{"node_id": node_id, "widget_name": widget_name, "type": kind, "value": value}) |
|
|
|
return (signal,) |
|
|
|
|
|
class ImpactNodeSetMuteState: |
|
@classmethod |
|
def INPUT_TYPES(cls): |
|
return {"required": { |
|
"signal": (any_typ,), |
|
"node_id": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}), |
|
"set_state": ("BOOLEAN", {"default": True, "label_on": "active", "label_off": "mute"}), |
|
} |
|
} |
|
|
|
FUNCTION = "doit" |
|
|
|
CATEGORY = "ImpactPack/Logic/_for_test" |
|
RETURN_TYPES = (any_typ,) |
|
RETURN_NAMES = ("signal_opt",) |
|
OUTPUT_NODE = True |
|
|
|
def doit(self, signal, node_id, set_state): |
|
PromptServer.instance.send_sync("impact-node-mute-state", {"node_id": node_id, "is_active": set_state}) |
|
return (signal,) |
|
|
|
|
|
class ImpactSleep: |
|
@classmethod |
|
def INPUT_TYPES(cls): |
|
return {"required": { |
|
"signal": (any_typ,), |
|
"seconds": ("FLOAT", {"default": 0.5, "min": 0, "max": 3600}), |
|
} |
|
} |
|
|
|
FUNCTION = "doit" |
|
|
|
CATEGORY = "ImpactPack/Logic/_for_test" |
|
RETURN_TYPES = (any_typ,) |
|
RETURN_NAMES = ("signal_opt",) |
|
OUTPUT_NODE = True |
|
|
|
def doit(self, signal, seconds): |
|
time.sleep(seconds) |
|
return (signal,) |
|
|
|
|
|
error_skip_flag = False |
|
try: |
|
import sys |
|
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 |
|
|
|
sys.__comfyui_manager_register_message_collapse(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 = {} |
|
for link in workflow['links']: |
|
links[link[0]] = link[1:] |
|
for node in workflow['nodes']: |
|
nodes[str(node['id'])] = node |
|
|
|
return nodes, links |
|
|
|
|
|
class ImpactControlBridge: |
|
@classmethod |
|
def INPUT_TYPES(cls): |
|
return {"required": { |
|
"value": (any_typ,), |
|
"mode": ("BOOLEAN", {"default": True, "label_on": "pass", "label_off": "block"}), |
|
}, |
|
"hidden": {"unique_id": "UNIQUE_ID", "prompt": "PROMPT", "extra_pnginfo": "EXTRA_PNGINFO"} |
|
} |
|
|
|
FUNCTION = "doit" |
|
|
|
CATEGORY = "ImpactPack/Logic/_for_test" |
|
RETURN_TYPES = (any_typ,) |
|
RETURN_NAMES = ("value",) |
|
OUTPUT_NODE = True |
|
|
|
def doit(self, value, mode, unique_id, prompt, extra_pnginfo): |
|
global error_skip_flag |
|
|
|
nodes, links = workflow_to_map(extra_pnginfo['workflow']) |
|
|
|
outputs = [str(links[link][2]) for link in nodes[unique_id]['outputs'][0]['links']] |
|
|
|
prompt_set = set(prompt.keys()) |
|
output_set = set(outputs) |
|
|
|
if mode: |
|
should_active_but_muted = output_set - prompt_set |
|
if len(should_active_but_muted) > 0: |
|
PromptServer.instance.send_sync("impact-bridge-continue", {"node_id": unique_id, 'actives': list(should_active_but_muted)}) |
|
error_skip_flag = True |
|
raise Exception("IMPACT-PACK-SIGNAL: STOP CONTROL BRIDGE\nIf you see this message, your ComfyUI-Manager is outdated. Please update it.") |
|
else: |
|
should_muted_but_active = prompt_set.intersection(output_set) |
|
if len(should_muted_but_active) > 0: |
|
PromptServer.instance.send_sync("impact-bridge-continue", {"node_id": unique_id, 'mutes': list(should_muted_but_active)}) |
|
error_skip_flag = True |
|
raise Exception("IMPACT-PACK-SIGNAL: STOP CONTROL BRIDGE\nIf you see this message, your ComfyUI-Manager is outdated. Please update it.") |
|
|
|
return (value, ) |
|
|
|
|
|
original_handle_execution = execution.PromptExecutor.handle_execution_error |
|
|
|
|
|
def handle_execution_error(**kwargs): |
|
print(f" handled") |
|
execution.PromptExecutor.handle_execution_error(**kwargs) |
|
|
|
|