845 lines
24 KiB
Python
845 lines
24 KiB
Python
import math
|
|
import re
|
|
from .tools import VariantSupport, SmartType
|
|
from .base_node import NODE_POSTFIX, ArithmeticNode, BooleanNode, ConversionNode, UtilityNode, ConstantsNode, PrimitiveNode
|
|
|
|
# Create a NUMBER type that accepts both INT and FLOAT
|
|
NUMBER = SmartType("INT,FLOAT")
|
|
|
|
@VariantSupport()
|
|
class IntegerInput(PrimitiveNode):
|
|
"""
|
|
Output an integer value.
|
|
"""
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"value": ("INT", {"default": 0, "min": -0xffffffffffffffff, "max": 0xffffffffffffffff, "step": 1}),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("INT",)
|
|
RETURN_NAMES = ("value",)
|
|
FUNCTION = "output"
|
|
|
|
def output(self, value):
|
|
return (value,)
|
|
|
|
@VariantSupport()
|
|
class FloatInput(PrimitiveNode):
|
|
"""
|
|
Output a float value.
|
|
"""
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"value": ("FLOAT", {"default": 0.0, "min": -999999999999.0, "max": 999999999999.0, "step": 0.001}),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("FLOAT",)
|
|
RETURN_NAMES = ("value",)
|
|
FUNCTION = "output"
|
|
|
|
def output(self, value):
|
|
return (value,)
|
|
|
|
@VariantSupport()
|
|
class PreciseFloatInput(PrimitiveNode):
|
|
"""
|
|
Output a precise float value.
|
|
"""
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"value": ("FLOAT", {"default": 0.0, "min": -999999999999.0, "max": 999999999999.0, "step": 0.0000000001}),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("FLOAT",)
|
|
RETURN_NAMES = ("value",)
|
|
FUNCTION = "output"
|
|
|
|
def output(self, value):
|
|
return (value,)
|
|
|
|
@VariantSupport()
|
|
class BooleanInput(PrimitiveNode):
|
|
"""
|
|
Output a boolean value.
|
|
"""
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"value": ("BOOLEAN", {"default": False}),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("BOOLEAN",)
|
|
RETURN_NAMES = ("value",)
|
|
FUNCTION = "output"
|
|
|
|
def output(self, value):
|
|
return (value,)
|
|
|
|
@VariantSupport()
|
|
class StringInput(PrimitiveNode):
|
|
"""
|
|
Output a string value.
|
|
"""
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"value": ("STRING", {"default": "",}),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("STRING",)
|
|
RETURN_NAMES = ("value",)
|
|
FUNCTION = "output"
|
|
|
|
def output(self, value):
|
|
return (value,)
|
|
|
|
@VariantSupport()
|
|
class IntToType(ConversionNode):
|
|
"""
|
|
Convert an integer to various types.
|
|
"""
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"value": ("INT", {"default": 0, "min": -0xffffffffffffffff, "max": 0xffffffffffffffff, "step": 1}),
|
|
"output_type": (["INT", "FLOAT", "STRING", "BOOLEAN"],),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("*",)
|
|
RETURN_NAMES = ("value",)
|
|
FUNCTION = "convert"
|
|
|
|
def convert(self, value, output_type):
|
|
if output_type == "INT":
|
|
return (value,)
|
|
elif output_type == "FLOAT":
|
|
return (float(value),)
|
|
elif output_type == "STRING":
|
|
return (str(value),)
|
|
elif output_type == "BOOLEAN":
|
|
return (bool(value),)
|
|
|
|
@VariantSupport()
|
|
class FloatToType(ConversionNode):
|
|
"""
|
|
Convert a float to various types.
|
|
"""
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"value": ("FLOAT", {"default": 0.0, "min": -999999999999.0, "max": 999999999999.0, "step": 0.001}),
|
|
"output_type": (["INT", "FLOAT", "STRING", "BOOLEAN"],),
|
|
},
|
|
"optional": {
|
|
"round_method": (["round", "floor", "ceil", "trunc"], {"default": "round"}),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("*",)
|
|
RETURN_NAMES = ("value",)
|
|
FUNCTION = "convert"
|
|
|
|
def convert(self, value, output_type, round_method="round"):
|
|
if output_type == "INT":
|
|
if round_method == "round":
|
|
return (round(value),)
|
|
elif round_method == "floor":
|
|
return (math.floor(value),)
|
|
elif round_method == "ceil":
|
|
return (math.ceil(value),)
|
|
elif round_method == "trunc":
|
|
return (math.trunc(value),)
|
|
elif output_type == "FLOAT":
|
|
return (value,)
|
|
elif output_type == "STRING":
|
|
return (str(value),)
|
|
elif output_type == "BOOLEAN":
|
|
return (bool(value),)
|
|
|
|
@VariantSupport()
|
|
class ToBool(ConversionNode):
|
|
"""
|
|
Convert any value to boolean with optional invert.
|
|
"""
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"value": ("*",),
|
|
},
|
|
"optional": {
|
|
"invert": ("BOOLEAN", {"default": False}),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("BOOLEAN",)
|
|
RETURN_NAMES = ("result",)
|
|
FUNCTION = "convert"
|
|
|
|
def convert(self, value, invert=False):
|
|
try:
|
|
result = bool(value)
|
|
except:
|
|
# If conversion fails, assume it's something (True)
|
|
result = True
|
|
|
|
if invert:
|
|
result = not result
|
|
|
|
return (result,)
|
|
|
|
@VariantSupport()
|
|
class BasicMath(ArithmeticNode):
|
|
"""
|
|
Basic mathematical operations between two numbers.
|
|
"""
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"a": (NUMBER, {"default": 0.0}),
|
|
"b": (NUMBER, {"default": 0.0}),
|
|
"operation": (["+", "-", "*", "/", "//", "%", "**", "min", "max"],),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("*",)
|
|
RETURN_NAMES = ("result",)
|
|
FUNCTION = "calculate"
|
|
|
|
def calculate(self, a, b, operation):
|
|
# Determine if we should return int or float based on input types and operation
|
|
is_int_operation = isinstance(a, int) and isinstance(b, int) and operation != "/"
|
|
|
|
try:
|
|
if operation == "+":
|
|
result = a + b
|
|
elif operation == "-":
|
|
result = a - b
|
|
elif operation == "*":
|
|
result = a * b
|
|
elif operation == "/":
|
|
if b == 0:
|
|
return (float('inf') if a > 0 else float('-inf'),)
|
|
result = a / b
|
|
is_int_operation = False # Division always returns float
|
|
elif operation == "//":
|
|
if b == 0:
|
|
return (float('inf') if a > 0 else float('-inf'),)
|
|
result = a // b
|
|
elif operation == "%":
|
|
if b == 0:
|
|
return (float('nan'),)
|
|
result = a % b
|
|
elif operation == "**":
|
|
result = a ** b
|
|
# Power can return float even with int inputs
|
|
if not isinstance(result, int):
|
|
is_int_operation = False
|
|
elif operation == "min":
|
|
result = min(a, b)
|
|
elif operation == "max":
|
|
result = max(a, b)
|
|
|
|
# Return as int if both inputs were int and operation preserves int type
|
|
if is_int_operation and isinstance(result, (int, float)) and result == int(result):
|
|
return (int(result),)
|
|
else:
|
|
return (float(result),)
|
|
except:
|
|
return (float('nan'),)
|
|
|
|
@VariantSupport()
|
|
class IntMath(ArithmeticNode):
|
|
"""
|
|
Basic mathematical operations between two integers.
|
|
"""
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"a": ("INT", {"default": 0, "min": -0xffffffffffffffff, "max": 0xffffffffffffffff, "step": 1}),
|
|
"b": ("INT", {"default": 0, "min": -0xffffffffffffffff, "max": 0xffffffffffffffff, "step": 1}),
|
|
"operation": (["+", "-", "*", "//", "%", "**", "min", "max", "&", "|", "^", "<<", ">>"],),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("INT",)
|
|
RETURN_NAMES = ("result",)
|
|
FUNCTION = "calculate"
|
|
|
|
def calculate(self, a, b, operation):
|
|
try:
|
|
if operation == "+":
|
|
return (a + b,)
|
|
elif operation == "-":
|
|
return (a - b,)
|
|
elif operation == "*":
|
|
return (a * b,)
|
|
elif operation == "//":
|
|
if b == 0:
|
|
return (0,)
|
|
return (a // b,)
|
|
elif operation == "%":
|
|
if b == 0:
|
|
return (0,)
|
|
return (a % b,)
|
|
elif operation == "**":
|
|
return (a ** b,)
|
|
elif operation == "min":
|
|
return (min(a, b),)
|
|
elif operation == "max":
|
|
return (max(a, b),)
|
|
elif operation == "&":
|
|
return (a & b,)
|
|
elif operation == "|":
|
|
return (a | b,)
|
|
elif operation == "^":
|
|
return (a ^ b,)
|
|
elif operation == "<<":
|
|
return (a << b,)
|
|
elif operation == ">>":
|
|
return (a >> b,)
|
|
except:
|
|
return (0,)
|
|
|
|
@VariantSupport()
|
|
class UnaryMath(ArithmeticNode):
|
|
"""
|
|
Unary mathematical operations on a single number.
|
|
"""
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"value": (NUMBER, {"default": 0.0}),
|
|
"operation": (["abs", "neg", "sqrt", "sin", "cos", "tan", "log", "log10", "exp", "floor", "ceil", "round"],),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("*",)
|
|
RETURN_NAMES = ("result",)
|
|
FUNCTION = "calculate"
|
|
|
|
def calculate(self, value, operation):
|
|
# Determine return type based on operation and input
|
|
preserve_int = isinstance(value, int) and operation in ["abs", "neg"]
|
|
|
|
try:
|
|
if operation == "abs":
|
|
result = abs(value)
|
|
elif operation == "neg":
|
|
result = -value
|
|
elif operation == "sqrt":
|
|
result = math.sqrt(abs(value))
|
|
preserve_int = False
|
|
elif operation == "sin":
|
|
result = math.sin(value)
|
|
preserve_int = False
|
|
elif operation == "cos":
|
|
result = math.cos(value)
|
|
preserve_int = False
|
|
elif operation == "tan":
|
|
result = math.tan(value)
|
|
preserve_int = False
|
|
elif operation == "log":
|
|
result = math.log(abs(value)) if value != 0 else float('-inf')
|
|
preserve_int = False
|
|
elif operation == "log10":
|
|
result = math.log10(abs(value)) if value != 0 else float('-inf')
|
|
preserve_int = False
|
|
elif operation == "exp":
|
|
result = math.exp(value)
|
|
preserve_int = False
|
|
elif operation == "floor":
|
|
result = math.floor(value)
|
|
preserve_int = isinstance(value, int)
|
|
elif operation == "ceil":
|
|
result = math.ceil(value)
|
|
preserve_int = isinstance(value, int)
|
|
elif operation == "round":
|
|
result = round(value)
|
|
preserve_int = isinstance(value, int)
|
|
|
|
if preserve_int:
|
|
return (int(result),)
|
|
else:
|
|
return (float(result),)
|
|
except:
|
|
return (float('nan'),)
|
|
|
|
@VariantSupport()
|
|
class MathConstants(ConstantsNode):
|
|
"""
|
|
Common mathematical constants.
|
|
"""
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"constant": (["pi", "e", "tau", "inf", "nan"],),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("FLOAT",)
|
|
RETURN_NAMES = ("value",)
|
|
FUNCTION = "get_constant"
|
|
|
|
def get_constant(self, constant):
|
|
if constant == "pi":
|
|
return (math.pi,)
|
|
elif constant == "e":
|
|
return (math.e,)
|
|
elif constant == "tau":
|
|
return (math.tau,)
|
|
elif constant == "inf":
|
|
return (float('inf'),)
|
|
elif constant == "nan":
|
|
return (float('nan'),)
|
|
|
|
@VariantSupport()
|
|
class NumberRound(UtilityNode):
|
|
"""
|
|
Round a number to specified decimal places.
|
|
"""
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"value": (NUMBER, {"default": 0.0}),
|
|
"decimals": ("INT", {"default": 2, "min": 0, "max": 10, "step": 1}),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("*",)
|
|
RETURN_NAMES = ("rounded",)
|
|
FUNCTION = "round_number"
|
|
|
|
def round_number(self, value, decimals):
|
|
result = round(value, decimals)
|
|
# If input was int and decimals is 0, return int
|
|
if isinstance(value, int) and decimals == 0:
|
|
return (int(result),)
|
|
else:
|
|
return (float(result),)
|
|
|
|
@VariantSupport()
|
|
class NumberClamp(UtilityNode):
|
|
"""
|
|
Clamp a number between minimum and maximum values.
|
|
"""
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"value": (NUMBER, {"default": 0.0}),
|
|
"min_value": (NUMBER, {"default": 0.0}),
|
|
"max_value": (NUMBER, {"default": 1.0}),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("*",)
|
|
RETURN_NAMES = ("clamped",)
|
|
FUNCTION = "clamp"
|
|
|
|
def clamp(self, value, min_value, max_value):
|
|
result = max(min_value, min(max_value, value))
|
|
# If all inputs are int, return int
|
|
if all(isinstance(x, int) for x in [value, min_value, max_value]):
|
|
return (int(result),)
|
|
else:
|
|
return (float(result),)
|
|
|
|
@VariantSupport()
|
|
class NumberLerp(UtilityNode):
|
|
"""
|
|
Linear interpolation between two values.
|
|
"""
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"a": (NUMBER, {"default": 0.0}),
|
|
"b": (NUMBER, {"default": 1.0}),
|
|
"t": (NUMBER, {"default": 0.5}),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("*",)
|
|
RETURN_NAMES = ("result",)
|
|
FUNCTION = "lerp"
|
|
|
|
def lerp(self, a, b, t):
|
|
result = a + t * (b - a)
|
|
# Lerp usually returns float due to multiplication
|
|
# Only return int if result is whole number and inputs were int
|
|
if all(isinstance(x, int) for x in [a, b, t]) and result == int(result):
|
|
return (int(result),)
|
|
else:
|
|
return (float(result),)
|
|
|
|
@VariantSupport()
|
|
class NumberRange(UtilityNode):
|
|
"""
|
|
Check if a number is within a range.
|
|
"""
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"value": (NUMBER, {"default": 0.0}),
|
|
"min_value": (NUMBER, {"default": 0.0}),
|
|
"max_value": (NUMBER, {"default": 1.0}),
|
|
"inclusive": ("BOOLEAN", {"default": True}),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("BOOLEAN",)
|
|
RETURN_NAMES = ("in_range",)
|
|
FUNCTION = "check_range"
|
|
|
|
def check_range(self, value, min_value, max_value, inclusive):
|
|
if inclusive:
|
|
return (min_value <= value <= max_value,)
|
|
else:
|
|
return (min_value < value < max_value,)
|
|
|
|
@VariantSupport()
|
|
class NumberComparison(BooleanNode):
|
|
"""
|
|
Compare two numbers and return a boolean result.
|
|
"""
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"a": (NUMBER, {"default": 0.0}),
|
|
"b": (NUMBER, {"default": 0.0}),
|
|
"operation": (["==", "!=", "<", ">", "<=", ">="],),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("BOOLEAN",)
|
|
RETURN_NAMES = ("result",)
|
|
FUNCTION = "compare"
|
|
|
|
def compare(self, a, b, operation):
|
|
if operation == "==":
|
|
return (a == b,)
|
|
elif operation == "!=":
|
|
return (a != b,)
|
|
elif operation == "<":
|
|
return (a < b,)
|
|
elif operation == ">":
|
|
return (a > b,)
|
|
elif operation == "<=":
|
|
return (a <= b,)
|
|
elif operation == ">=":
|
|
return (a >= b,)
|
|
|
|
@VariantSupport()
|
|
class IntegerComparison(BooleanNode):
|
|
"""
|
|
Compare two integers and return a boolean result.
|
|
"""
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"a": ("INT", {"default": 0, "min": -0xffffffffffffffff, "max": 0xffffffffffffffff, "step": 1}),
|
|
"b": ("INT", {"default": 0, "min": -0xffffffffffffffff, "max": 0xffffffffffffffff, "step": 1}),
|
|
"operation": (["==", "!=", "<", ">", "<=", ">="],),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("BOOLEAN",)
|
|
RETURN_NAMES = ("result",)
|
|
FUNCTION = "compare"
|
|
|
|
def compare(self, a, b, operation):
|
|
if operation == "==":
|
|
return (a == b,)
|
|
elif operation == "!=":
|
|
return (a != b,)
|
|
elif operation == "<":
|
|
return (a < b,)
|
|
elif operation == ">":
|
|
return (a > b,)
|
|
elif operation == "<=":
|
|
return (a <= b,)
|
|
elif operation == ">=":
|
|
return (a >= b,)
|
|
|
|
@VariantSupport()
|
|
class FloatComparison(BooleanNode):
|
|
"""
|
|
Compare two floats and return a boolean result.
|
|
"""
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"a": ("FLOAT", {"default": 0.0, "min": -999999999999.0, "max": 999999999999.0, "step": 0.001}),
|
|
"b": ("FLOAT", {"default": 0.0, "min": -999999999999.0, "max": 999999999999.0, "step": 0.001}),
|
|
"operation": (["==", "!=", "<", ">", "<=", ">="],),
|
|
},
|
|
"optional": {
|
|
"tolerance": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.0001}),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("BOOLEAN",)
|
|
RETURN_NAMES = ("result",)
|
|
FUNCTION = "compare"
|
|
|
|
def compare(self, a, b, operation, tolerance=0.0):
|
|
# Handle floating point comparison with optional tolerance
|
|
if tolerance > 0 and operation in ["==", "!="]:
|
|
equal = abs(a - b) <= tolerance
|
|
if operation == "==":
|
|
return (equal,)
|
|
else: # !=
|
|
return (not equal,)
|
|
|
|
if operation == "==":
|
|
return (a == b,)
|
|
elif operation == "!=":
|
|
return (a != b,)
|
|
elif operation == "<":
|
|
return (a < b,)
|
|
elif operation == ">":
|
|
return (a > b,)
|
|
elif operation == "<=":
|
|
return (a <= b,)
|
|
elif operation == ">=":
|
|
return (a >= b,)
|
|
|
|
@VariantSupport()
|
|
class StringComparison(BooleanNode):
|
|
"""
|
|
Compare and manipulate strings with various operations.
|
|
"""
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"a": ("STRING", {"multiline": False}),
|
|
"b": ("STRING", {"multiline": False}),
|
|
"operation": (["a == b", "a != b", "a IN b", "a MATCH REGEX(b)", "a BEGINSWITH b", "a ENDSWITH b"],),
|
|
"case_sensitive": ("BOOLEAN", {"default": True}),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("BOOLEAN",)
|
|
RETURN_NAMES = ("result",)
|
|
FUNCTION = "compare"
|
|
|
|
def compare(self, a, b, operation, case_sensitive):
|
|
if not case_sensitive:
|
|
a = a.lower()
|
|
b = b.lower()
|
|
|
|
if operation == "a == b":
|
|
return (a == b,)
|
|
elif operation == "a != b":
|
|
return (a != b,)
|
|
elif operation == "a IN b":
|
|
return (a in b,)
|
|
elif operation == "a MATCH REGEX(b)":
|
|
try:
|
|
return (re.match(b, a) is not None,)
|
|
except:
|
|
return (False,)
|
|
elif operation == "a BEGINSWITH b":
|
|
return (a.startswith(b),)
|
|
elif operation == "a ENDSWITH b":
|
|
return (a.endswith(b),)
|
|
|
|
@VariantSupport()
|
|
class BooleanLogic(BooleanNode):
|
|
"""
|
|
Boolean logic operations.
|
|
"""
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"a": ("BOOLEAN",),
|
|
"b": ("BOOLEAN",),
|
|
"operation": (["AND", "OR", "XOR", "NAND", "NOR", "XNOR"],),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("BOOLEAN",)
|
|
RETURN_NAMES = ("result",)
|
|
FUNCTION = "logic_operation"
|
|
|
|
def logic_operation(self, a, b, operation):
|
|
if operation == "AND":
|
|
return (a and b,)
|
|
elif operation == "OR":
|
|
return (a or b,)
|
|
elif operation == "XOR":
|
|
return (a ^ b,)
|
|
elif operation == "NAND":
|
|
return (not (a and b),)
|
|
elif operation == "NOR":
|
|
return (not (a or b),)
|
|
elif operation == "XNOR":
|
|
return (not (a ^ b),)
|
|
|
|
@VariantSupport()
|
|
class BooleanUnary(BooleanNode):
|
|
"""
|
|
Unary boolean operations.
|
|
"""
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"value": ("BOOLEAN",),
|
|
"operation": (["NOT", "IDENTITY"],),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("BOOLEAN",)
|
|
RETURN_NAMES = ("result",)
|
|
FUNCTION = "unary_operation"
|
|
|
|
def unary_operation(self, value, operation):
|
|
if operation == "NOT":
|
|
return (not value,)
|
|
elif operation == "IDENTITY":
|
|
return (value,)
|
|
|
|
MATH_NODE_CLASS_MAPPINGS = {
|
|
"IntegerInput": IntegerInput,
|
|
"FloatInput": FloatInput,
|
|
"PreciseFloatInput": PreciseFloatInput,
|
|
"BooleanInput": BooleanInput,
|
|
"StringInput": StringInput,
|
|
"IntToType": IntToType,
|
|
"FloatToType": FloatToType,
|
|
"ToBool": ToBool,
|
|
"BasicMath": BasicMath,
|
|
"IntMath": IntMath,
|
|
"UnaryMath": UnaryMath,
|
|
"MathConstants": MathConstants,
|
|
"NumberRound": NumberRound,
|
|
"NumberClamp": NumberClamp,
|
|
"NumberLerp": NumberLerp,
|
|
"NumberRange": NumberRange,
|
|
"NumberComparison": NumberComparison,
|
|
"IntegerComparison": IntegerComparison,
|
|
"FloatComparison": FloatComparison,
|
|
"StringComparison": StringComparison,
|
|
"BooleanLogic": BooleanLogic,
|
|
"BooleanUnary": BooleanUnary,
|
|
}
|
|
|
|
MATH_NODE_DISPLAY_NAME_MAPPINGS = {
|
|
"IntegerInput": f"Integer {NODE_POSTFIX}",
|
|
"FloatInput": f"Float {NODE_POSTFIX}",
|
|
"PreciseFloatInput": f"Precise Float {NODE_POSTFIX}",
|
|
"BooleanInput": f"Boolean {NODE_POSTFIX}",
|
|
"StringInput": f"String {NODE_POSTFIX}",
|
|
"IntToType": f"Int to Type {NODE_POSTFIX}",
|
|
"FloatToType": f"Float to Type {NODE_POSTFIX}",
|
|
"ToBool": f"To Bool {NODE_POSTFIX}",
|
|
"BasicMath": f"Basic Math {NODE_POSTFIX}",
|
|
"IntMath": f"Int Math {NODE_POSTFIX}",
|
|
"UnaryMath": f"Unary Math {NODE_POSTFIX}",
|
|
"MathConstants": f"Math Constants {NODE_POSTFIX}",
|
|
"NumberRound": f"Number Round {NODE_POSTFIX}",
|
|
"NumberClamp": f"Number Clamp {NODE_POSTFIX}",
|
|
"NumberLerp": f"Number Lerp {NODE_POSTFIX}",
|
|
"NumberRange": f"Number Range {NODE_POSTFIX}",
|
|
"NumberComparison": f"Number Comparison {NODE_POSTFIX}",
|
|
"IntegerComparison": f"Integer Comparison {NODE_POSTFIX}",
|
|
"FloatComparison": f"Float Comparison {NODE_POSTFIX}",
|
|
"StringComparison": f"String Comparison {NODE_POSTFIX}",
|
|
"BooleanLogic": f"Boolean Logic {NODE_POSTFIX}",
|
|
"BooleanUnary": f"Boolean Unary {NODE_POSTFIX}",
|
|
} |