[Added] Generic AND/OR (NAND/NOR/NOT)

- Two nodes supporting Any as input
- Optional invert
- Dynamic inputs
This commit is contained in:
Salvador E. Tropea
2025-11-20 13:53:20 -03:00
parent 318cbbfa36
commit 9976e80394
+64
View File
@@ -1,4 +1,5 @@
from inspect import cleandoc
from typing import Any
try:
from comfy.comfy_types.node_typing import IO, ComfyNodeABC
@@ -12,6 +13,9 @@ except:
ANY = "*"
ComfyNodeABC = object
from ._dynamic_input import ContainsDynamicDict
class BooleanAnd(ComfyNodeABC):
"""
Returns the logical AND result of two boolean values.
@@ -155,20 +159,80 @@ class BooleanXor(ComfyNodeABC):
return (input1 != input2,)
class GenericOr(ComfyNodeABC):
"""
Returns the logical N/OR result of one or more values.
This node takes a dynamic number of inputs and returns their logical N/OR result.
Note that values are evaluated according Python's rules. I.e. an empty string is
`false`, an integer 0 is also `false`, etc.
"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"invert": (IO.BOOLEAN, {"default": False}),
},
"optional": ContainsDynamicDict({
"item_0": (IO.ANY, {"_dynamic": "number", "widgetType": "STRING"}),
})
}
RETURN_TYPES = (IO.BOOLEAN,)
CATEGORY = "Basic/BOOLEAN"
DESCRIPTION = cleandoc(__doc__ or "")
FUNCTION = "or_operation"
def or_operation(self, invert: bool, **kwargs: list[Any]) -> tuple[bool]:
return (any(kwargs.values()) ^ invert,)
class GenericAnd(ComfyNodeABC):
"""
Returns the logical N/AND result of one or more values.
This node takes a dynamic number of inputs and returns their logical N/AND result.
Note that values are evaluated according Python's rules. I.e. an empty string is
`false`, an integer 0 is also `false`, etc.
"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"invert": (IO.BOOLEAN, {"default": False}),
},
"optional": ContainsDynamicDict({
"item_0": (IO.ANY, {"_dynamic": "number", "widgetType": "STRING", "default": "True"}),
})
}
RETURN_TYPES = (IO.BOOLEAN,)
CATEGORY = "Basic/BOOLEAN"
DESCRIPTION = cleandoc(__doc__ or "")
FUNCTION = "and_operation"
def and_operation(self, invert: bool, **kwargs: list[Any]) -> tuple[bool]:
return (all(kwargs.values()) ^ invert,)
NODE_CLASS_MAPPINGS = {
"Basic data handling: Boolean And": BooleanAnd,
"Basic data handling: Generic And": GenericAnd,
"Basic data handling: Boolean Nand": BooleanNand,
"Basic data handling: Boolean Nor": BooleanNor,
"Basic data handling: Boolean Not": BooleanNot,
"Basic data handling: Boolean Or": BooleanOr,
"Basic data handling: Generic Or": GenericOr,
"Basic data handling: Boolean Xor": BooleanXor,
}
NODE_DISPLAY_NAME_MAPPINGS = {
"Basic data handling: Boolean And": "and",
"Basic data handling: Generic And": "and (generic)",
"Basic data handling: Boolean Nand": "nand",
"Basic data handling: Boolean Nor": "nor",
"Basic data handling: Boolean Not": "not",
"Basic data handling: Boolean Or": "or",
"Basic data handling: Generic Or": "or (generic)",
"Basic data handling: Boolean Xor": "xor",
}