mirror of
https://git.datalinker.icu/comfyanonymous/ComfyUI
synced 2026-08-02 03:40:03 +08:00
Add nodes for basic logic operation and math
This commit is contained in:
parent
a1864c01f2
commit
4a9838c3ef
108
comfy_extras/nodes_logic.py
Normal file
108
comfy_extras/nodes_logic.py
Normal file
@ -0,0 +1,108 @@
|
||||
from comfy.comfy_types.node_typing import IO, ComfyNodeABC
|
||||
|
||||
class LogicIF(ComfyNodeABC):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"if_condition": (IO.BOOLEAN, {}),
|
||||
"when_true": (IO.ANY, {})
|
||||
},
|
||||
"optional": {
|
||||
"when_false": (IO.ANY, {})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = (IO.ANY,)
|
||||
RETURN_NAMES = ("result",)
|
||||
FUNCTION = "execute"
|
||||
CATEGORY = "utils/logic"
|
||||
|
||||
def execute(self, if_condition, when_true, when_false, **kwargs):
|
||||
if if_condition:
|
||||
return when_true,
|
||||
else:
|
||||
return when_false,
|
||||
|
||||
class LogicAND(ComfyNodeABC):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"input_a": (IO.BOOLEAN, {}),
|
||||
"input_b": (IO.BOOLEAN, {})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = (IO.BOOLEAN,)
|
||||
FUNCTION = "execute"
|
||||
CATEGORY = "utils/logic"
|
||||
|
||||
def execute(self, input_a, input_b, **kwargs):
|
||||
return input_a and input_b,
|
||||
|
||||
class LogicOR(ComfyNodeABC):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"input_a": (IO.BOOLEAN, {}),
|
||||
"input_b": (IO.BOOLEAN, {})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = (IO.BOOLEAN,)
|
||||
FUNCTION = "execute"
|
||||
CATEGORY = "utils/logic"
|
||||
|
||||
def execute(self, input_a, input_b, **kwargs):
|
||||
return input_a or input_b,
|
||||
|
||||
class LogicNOT(ComfyNodeABC):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"input": (IO.BOOLEAN, {})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = (IO.BOOLEAN,)
|
||||
FUNCTION = "execute"
|
||||
CATEGORY = "utils/logic"
|
||||
|
||||
def execute(self, input, **kwargs):
|
||||
return not input,
|
||||
|
||||
class LogicXOR(ComfyNodeABC):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"input_a": (IO.BOOLEAN, {}),
|
||||
"input_b": (IO.BOOLEAN, {})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = (IO.BOOLEAN,)
|
||||
FUNCTION = "execute"
|
||||
CATEGORY = "utils/logic"
|
||||
|
||||
def execute(self, input_a, input_b, **kwargs):
|
||||
return input_a != input_b,
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"LogicIF": LogicIF,
|
||||
"LogicAND": LogicAND,
|
||||
"LogicOR": LogicOR,
|
||||
"LogicNOT": LogicNOT,
|
||||
"LogicXOR": LogicXOR
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"LogicIF": "IF",
|
||||
"LogicAND": "AND",
|
||||
"LogicOR": "OR",
|
||||
"LogicNOT": "NOT",
|
||||
"LogicXOR": "XOR"
|
||||
}
|
||||
466
comfy_extras/nodes_math.py
Normal file
466
comfy_extras/nodes_math.py
Normal file
@ -0,0 +1,466 @@
|
||||
from comfy.comfy_types.node_typing import IO, ComfyNodeABC
|
||||
import math
|
||||
|
||||
class MathAdd(ComfyNodeABC):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"value_a": (IO.NUMBER, {}),
|
||||
"value_b": (IO.NUMBER, {})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = (IO.NUMBER,)
|
||||
RETURN_NAMES = ("result",)
|
||||
FUNCTION = "execute"
|
||||
CATEGORY = "utils/math"
|
||||
|
||||
def execute(self, value_a, value_b, **kwargs):
|
||||
return value_a + value_b,
|
||||
|
||||
class MathSubtract(ComfyNodeABC):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"value_a": (IO.NUMBER, {}),
|
||||
"value_b": (IO.NUMBER, {})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = (IO.NUMBER,)
|
||||
RETURN_NAMES = ("result",)
|
||||
FUNCTION = "execute"
|
||||
CATEGORY = "utils/math"
|
||||
|
||||
def execute(self, value_a, value_b, **kwargs):
|
||||
return value_a - value_b,
|
||||
|
||||
class MathMultiply(ComfyNodeABC):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"value_a": (IO.NUMBER, {}),
|
||||
"value_b": (IO.NUMBER, {})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = (IO.NUMBER,)
|
||||
RETURN_NAMES = ("result",)
|
||||
FUNCTION = "execute"
|
||||
CATEGORY = "utils/math"
|
||||
|
||||
def execute(self, value_a, value_b, **kwargs):
|
||||
return value_a * value_b,
|
||||
|
||||
class MathDivide(ComfyNodeABC):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"value_a": (IO.NUMBER, {}),
|
||||
"value_b": (IO.NUMBER, {}),
|
||||
"handle_zero": (IO.BOOLEAN, {"default": True})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = (IO.NUMBER,)
|
||||
RETURN_NAMES = ("result",)
|
||||
FUNCTION = "execute"
|
||||
CATEGORY = "utils/math"
|
||||
|
||||
def execute(self, value_a, value_b, handle_zero, **kwargs):
|
||||
if value_b == 0:
|
||||
if handle_zero:
|
||||
return 0,
|
||||
else:
|
||||
raise ValueError("Division by zero")
|
||||
return value_a / value_b,
|
||||
|
||||
class MathPower(ComfyNodeABC):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"base": (IO.NUMBER, {}),
|
||||
"exponent": (IO.NUMBER, {})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = (IO.NUMBER,)
|
||||
RETURN_NAMES = ("result",)
|
||||
FUNCTION = "execute"
|
||||
CATEGORY = "utils/math"
|
||||
|
||||
def execute(self, base, exponent, **kwargs):
|
||||
return base ** exponent,
|
||||
|
||||
class MathFloor(ComfyNodeABC):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"value": (IO.NUMBER, {}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = (IO.NUMBER,)
|
||||
RETURN_NAMES = ("result",)
|
||||
FUNCTION = "execute"
|
||||
CATEGORY = "utils/math"
|
||||
|
||||
def execute(self, value, **kwargs):
|
||||
return math.floor(value),
|
||||
|
||||
class MathNumberConvert(ComfyNodeABC):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"number_value": (IO.NUMBER, {}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = (IO.INT, IO.FLOAT,)
|
||||
RETURN_NAMES = ("result_int", "result_float",)
|
||||
FUNCTION = "execute"
|
||||
CATEGORY = "utils/math"
|
||||
|
||||
def execute(self, number_value, **kwargs):
|
||||
return int(number_value), float(number_value)
|
||||
|
||||
class MathCeil(ComfyNodeABC):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"value": (IO.NUMBER, {})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = (IO.NUMBER,)
|
||||
RETURN_NAMES = ("result",)
|
||||
FUNCTION = "execute"
|
||||
CATEGORY = "utils/math"
|
||||
|
||||
def execute(self, value, **kwargs):
|
||||
return math.ceil(value),
|
||||
|
||||
class MathRound(ComfyNodeABC):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"value": (IO.NUMBER, {}),
|
||||
"decimals": (IO.INT, {"default": 0, "min": 0, "max": 10})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = (IO.NUMBER,)
|
||||
RETURN_NAMES = ("result",)
|
||||
FUNCTION = "execute"
|
||||
CATEGORY = "utils/math"
|
||||
|
||||
def execute(self, value, decimals, **kwargs):
|
||||
return round(value, decimals),
|
||||
|
||||
class MathModulo(ComfyNodeABC):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"value_a": (IO.NUMBER, {}),
|
||||
"value_b": (IO.NUMBER, {}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = (IO.NUMBER,)
|
||||
RETURN_NAMES = ("result",)
|
||||
FUNCTION = "execute"
|
||||
CATEGORY = "utils/math"
|
||||
|
||||
def execute(self, value_a, value_b, **kwargs):
|
||||
if value_b == 0:
|
||||
return 0,
|
||||
return value_a % value_b,
|
||||
|
||||
class MathAbs(ComfyNodeABC):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"value": (IO.NUMBER, {})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = (IO.NUMBER,)
|
||||
RETURN_NAMES = ("result",)
|
||||
FUNCTION = "execute"
|
||||
CATEGORY = "utils/math"
|
||||
|
||||
def execute(self, value, **kwargs):
|
||||
return abs(value),
|
||||
|
||||
class MathSqrt(ComfyNodeABC):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"value": (IO.NUMBER, {})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = (IO.NUMBER,)
|
||||
RETURN_NAMES = ("result",)
|
||||
FUNCTION = "execute"
|
||||
CATEGORY = "utils/math"
|
||||
|
||||
def execute(self, value, **kwargs):
|
||||
if value < 0:
|
||||
return 0,
|
||||
return math.sqrt(value),
|
||||
|
||||
class MathSin(ComfyNodeABC):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"angle": (IO.NUMBER, {}),
|
||||
"unit": (IO.COMBO, {"options": ["Radians", "Degrees"]})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = (IO.NUMBER,)
|
||||
RETURN_NAMES = ("result",)
|
||||
FUNCTION = "execute"
|
||||
CATEGORY = "utils/math/trigonometry"
|
||||
|
||||
def execute(self, angle, unit, **kwargs):
|
||||
if unit == "Degrees":
|
||||
angle = math.radians(angle)
|
||||
return math.sin(angle),
|
||||
|
||||
class MathCos(ComfyNodeABC):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"angle": (IO.NUMBER, {}),
|
||||
"unit": (IO.COMBO, {"options": ["Radians", "Degrees"]})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = (IO.NUMBER,)
|
||||
RETURN_NAMES = ("result",)
|
||||
FUNCTION = "execute"
|
||||
CATEGORY = "utils/math/trigonometry"
|
||||
|
||||
def execute(self, angle, unit, **kwargs):
|
||||
if unit == "Degrees":
|
||||
angle = math.radians(angle)
|
||||
return math.cos(angle),
|
||||
|
||||
class MathTan(ComfyNodeABC):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"angle": (IO.NUMBER, {}),
|
||||
"unit": (IO.COMBO, {"options": ["Radians", "Degrees"]})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = (IO.NUMBER,)
|
||||
RETURN_NAMES = ("result",)
|
||||
FUNCTION = "execute"
|
||||
CATEGORY = "utils/math/trigonometry"
|
||||
|
||||
def execute(self, angle, unit, **kwargs):
|
||||
if unit == "Degrees":
|
||||
angle = math.radians(angle)
|
||||
return math.tan(angle),
|
||||
|
||||
class MathMin(ComfyNodeABC):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"value_a": (IO.NUMBER, {}),
|
||||
"value_b": (IO.NUMBER, {})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = (IO.NUMBER,)
|
||||
RETURN_NAMES = ("result",)
|
||||
FUNCTION = "execute"
|
||||
CATEGORY = "utils/math"
|
||||
|
||||
def execute(self, value_a, value_b, **kwargs):
|
||||
return min(value_a, value_b),
|
||||
|
||||
class MathMax(ComfyNodeABC):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"value_a": (IO.NUMBER, {}),
|
||||
"value_b": (IO.NUMBER, {})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = (IO.NUMBER,)
|
||||
RETURN_NAMES = ("result",)
|
||||
FUNCTION = "execute"
|
||||
CATEGORY = "utils/math"
|
||||
|
||||
def execute(self, value_a, value_b, **kwargs):
|
||||
return max(value_a, value_b),
|
||||
|
||||
class MathClamp(ComfyNodeABC):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"value": (IO.NUMBER, {}),
|
||||
"min_value": (IO.NUMBER, {}),
|
||||
"max_value": (IO.NUMBER, {})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = (IO.NUMBER,)
|
||||
RETURN_NAMES = ("result",)
|
||||
FUNCTION = "execute"
|
||||
CATEGORY = "utils/math"
|
||||
|
||||
def execute(self, value, min_value, max_value, **kwargs):
|
||||
return max(min(value, max_value), min_value),
|
||||
|
||||
class StringToNumber(ComfyNodeABC):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"string": (IO.STRING, {"multiline": False})
|
||||
},
|
||||
"optional": {
|
||||
"default_value": (IO.NUMBER, {})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = (IO.NUMBER,)
|
||||
RETURN_NAMES = ("result",)
|
||||
FUNCTION = "execute"
|
||||
CATEGORY = "utils/math"
|
||||
|
||||
def execute(self, string, **kwargs):
|
||||
default_value = kwargs.get("default_value")
|
||||
|
||||
if default_value is None:
|
||||
default_value = 0
|
||||
|
||||
try:
|
||||
if '.' in string:
|
||||
return float(string),
|
||||
else:
|
||||
return int(string),
|
||||
except (ValueError, TypeError):
|
||||
return default_value,
|
||||
|
||||
class NumberToString(ComfyNodeABC):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"number": (IO.NUMBER, {})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = (IO.STRING,)
|
||||
RETURN_NAMES = ("result",)
|
||||
FUNCTION = "execute"
|
||||
CATEGORY = "utils/math"
|
||||
|
||||
def execute(self, number, **kwargs):
|
||||
return str(number),
|
||||
|
||||
class MathCompare(ComfyNodeABC):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"value_a": (IO.NUMBER, {}),
|
||||
"value_b": (IO.NUMBER, {}),
|
||||
"comparison": (IO.COMBO, {"options": ["Equal", "Not Equal", "Greater Than", "Less Than", "Greater Than or Equal", "Less Than or Equal"]})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = (IO.BOOLEAN,)
|
||||
RETURN_NAMES = ("result",)
|
||||
FUNCTION = "execute"
|
||||
CATEGORY = "utils/math"
|
||||
|
||||
def execute(self, value_a, value_b, comparison, **kwargs):
|
||||
if comparison == "Equal":
|
||||
return value_a == value_b,
|
||||
elif comparison == "Not Equal":
|
||||
return value_a != value_b,
|
||||
elif comparison == "Greater Than":
|
||||
return value_a > value_b,
|
||||
elif comparison == "Less Than":
|
||||
return value_a < value_b,
|
||||
elif comparison == "Greater Than or Equal":
|
||||
return value_a >= value_b,
|
||||
elif comparison == "Less Than or Equal":
|
||||
return value_a <= value_b,
|
||||
else:
|
||||
return False,
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"MathAdd": MathAdd,
|
||||
"MathSubtract": MathSubtract,
|
||||
"MathMultiply": MathMultiply,
|
||||
"MathDivide": MathDivide,
|
||||
"MathPower": MathPower,
|
||||
"MathFloor": MathFloor,
|
||||
"MathCeil": MathCeil,
|
||||
"MathRound": MathRound,
|
||||
"MathModulo": MathModulo,
|
||||
"MathAbs": MathAbs,
|
||||
"MathSqrt": MathSqrt,
|
||||
"MathSin": MathSin,
|
||||
"MathCos": MathCos,
|
||||
"MathTan": MathTan,
|
||||
"MathMin": MathMin,
|
||||
"MathMax": MathMax,
|
||||
"MathClamp": MathClamp,
|
||||
"MathNumberConvert": MathNumberConvert,
|
||||
"StringToNumber": StringToNumber,
|
||||
"NumberToString": NumberToString,
|
||||
"MathCompare": MathCompare
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"MathAdd": "Add",
|
||||
"MathSubtract": "Subtract",
|
||||
"MathMultiply": "Multiply",
|
||||
"MathDivide": "Divide",
|
||||
"MathPower": "Power",
|
||||
"MathFloor": "Floor",
|
||||
"MathCeil": "Ceil",
|
||||
"MathRound": "Round",
|
||||
"MathModulo": "Modulo",
|
||||
"MathAbs": "Absolute",
|
||||
"MathSqrt": "Square Root",
|
||||
"MathSin": "Sine",
|
||||
"MathCos": "Cosine",
|
||||
"MathTan": "Tangent",
|
||||
"MathMin": "Minimum",
|
||||
"MathMax": "Maximum",
|
||||
"MathClamp": "Clamp",
|
||||
"MathNumberConvert": "Number Convert",
|
||||
"StringToNumber": "String To Number",
|
||||
"NumberToString": "Number To String",
|
||||
"MathCompare": "Compare"
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user