diff --git a/comfy_extras/nodes_logic_ops.py b/comfy_extras/nodes_logic_ops.py new file mode 100644 index 000000000..abc4b22c1 --- /dev/null +++ b/comfy_extras/nodes_logic_ops.py @@ -0,0 +1,89 @@ +# Credit to pythongosssss for the AnyType code +class AnyType(str): + def __ne__(self, __value: object) -> bool: + return False + +any = AnyType("*") + +class BooleanNOT: + @classmethod + def INPUT_TYPES(cls): + return {"required": {"value": ("BOOLEAN", {"default": True})}} + + RETURN_TYPES = ("BOOLEAN",) + RETURN_NAMES = ("NOT",) + CATEGORY = "utils/logic" + FUNCTION = "get_not" + + def get_not(self, value: bool) -> tuple[bool]: + return (not value,) + +class BooleanLogicGate: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "value1": ("BOOLEAN", {"default": True}), + "value2": ("BOOLEAN", {"default": True}), + "mode": (["AND", "OR", "NAND", "NOR", "XOR", "XNOR"],) + } + } + + RETURN_TYPES = ("BOOLEAN",) + RETURN_NAMES = ("output",) + CATEGORY = "utils/logic" + FUNCTION = "apply_operation" + + _OPS = { + "AND": lambda a, b: a and b, + "OR": lambda a, b: a or b, + "NAND": lambda a, b: not (a and b), + "NOR": lambda a, b: not (a or b), + "XOR": lambda a, b: a ^ b, + "XNOR": lambda a, b: not (a ^ b), + } + + def apply_operation(self, value1: bool, value2: bool, mode: str) -> tuple[bool]: + return (self._OPS[mode](value1, value2),) + +class BooleanSwitch: + @classmethod + def INPUT_TYPES(cls): + return { + "required": {"switch": ("BOOLEAN", {"default": True})}, + "optional": {"on_true": (any,), "on_false": (any,)} + } + + RETURN_TYPES = ("ANY",) + RETURN_NAMES = ("*",) + CATEGORY = "utils/logic" + FUNCTION = "switch" + + def switch(self, switch: bool, on_true=None, on_false=None) -> tuple: + return ((on_true if switch else on_false),) + +class OutputExists: + @classmethod + def INPUT_TYPES(cls): + return {"optional": {"variable": (any,)}} + + RETURN_TYPES = ("BOOLEAN",) + CATEGORY = "utils/logic" + FUNCTION = "test_existence" + + def test_existence(self, variable=None) -> tuple[bool]: + return (variable is not None,) + +NODE_CLASS_MAPPINGS = { + "BooleanNOT": BooleanNOT, + "BooleanLogicGate": BooleanLogicGate, + "BooleanSwitch": BooleanSwitch, + "OutputExists": OutputExists, + } + +NODE_DISPLAY_NAME_MAPPINGS = { + "BooleanNOT": "Boolean NOT", + "BooleanLogicGate": "Boolean Logic Gate", + "BooleanSwitch": "Boolean Switch", + "OutputExists": "Output Exists", + }