97 lines
3.0 KiB
Python
97 lines
3.0 KiB
Python
import math
|
|
|
|
|
|
class Calculator:
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"calc_expression": ("STRING", {"default": "0"}),
|
|
},
|
|
"optional": {
|
|
"value_a": ("FLOAT", {"default": 0.0, "step": 0.01, "forceInput": True}),
|
|
"value_b": ("FLOAT", {"default": 0.0, "step": 0.01, "forceInput": True}),
|
|
"value_c": ("FLOAT", {"default": 0.0, "step": 0.01, "forceInput": True}),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("FLOAT", "INT", "STRING")
|
|
RETURN_NAMES = ("result_float", "result_int", "result_string")
|
|
FUNCTION = "calculate"
|
|
CATEGORY = "utils"
|
|
OUTPUT_NODE = False
|
|
|
|
SAFE_NAMES = {
|
|
"abs": abs, "round": round, "min": min, "max": max,
|
|
"int": int, "float": float,
|
|
"sqrt": math.sqrt, "pow": pow,
|
|
"sin": math.sin, "cos": math.cos, "tan": math.tan,
|
|
"asin": math.asin, "acos": math.acos, "atan": math.atan,
|
|
"log": math.log, "log10": math.log10, "log2": math.log2,
|
|
"ceil": math.ceil, "floor": math.floor,
|
|
"pi": math.pi, "e": math.e,
|
|
}
|
|
|
|
def _at(self, value, i):
|
|
"""Get value at index i; scalar broadcasts, list uses index (clamped to length)."""
|
|
if isinstance(value, list):
|
|
if not value:
|
|
return 0.0
|
|
return float(value[min(i, len(value) - 1)])
|
|
return float(value)
|
|
|
|
def calculate(self, calc_expression="0", value_a=0.0, value_b=0.0, value_c=0.0):
|
|
expr = calc_expression.strip() if calc_expression else "0"
|
|
if not expr:
|
|
return (0.0, 0, "0")
|
|
|
|
lists = [x for x in (value_a, value_b, value_c) if isinstance(x, list)]
|
|
list_length = max(len(x) for x in lists) if lists else 1
|
|
if list_length == 0:
|
|
return (0.0, 0, "0")
|
|
|
|
safe_dict = dict(self.SAFE_NAMES)
|
|
safe_dict["__builtins__"] = {}
|
|
|
|
results_float = []
|
|
results_int = []
|
|
results_str = []
|
|
|
|
for i in range(list_length):
|
|
a = self._at(value_a, i)
|
|
b = self._at(value_b, i)
|
|
c = self._at(value_c, i)
|
|
safe_dict.update({"A": a, "B": b, "C": c})
|
|
|
|
try:
|
|
result = float(eval(expr, safe_dict))
|
|
except Exception as e:
|
|
print(f"[Calculator] Error evaluating '{expr}' at index {i}: {e}")
|
|
result = 0.0
|
|
|
|
results_float.append(result)
|
|
results_int.append(int(result))
|
|
results_str.append(str(result))
|
|
|
|
if list_length == 1:
|
|
return (results_float[0], results_int[0], results_str[0])
|
|
return (results_float, results_int, results_str)
|
|
|
|
|
|
class IntToFloat:
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"value": ("INT", {"default": 0, "forceInput": True}),
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("FLOAT",)
|
|
RETURN_NAMES = ("float",)
|
|
FUNCTION = "convert"
|
|
CATEGORY = "utils"
|
|
|
|
def convert(self, value):
|
|
return (float(value),)
|