import numpy from typing import Any, Callable, Mapping, TypeAlias Vec2: TypeAlias = tuple[float, float] VEC2_ZERO = (0.0, 0.0) DEFAULT_VEC2 = ("VEC2", {"default": VEC2_ZERO}) Vec3: TypeAlias = tuple[float, float, float] VEC3_ZERO = (0.0, 0.0, 0.0) DEFAULT_VEC3 = ("VEC3", {"default": VEC3_ZERO}) Vec4: TypeAlias = tuple[float, float, float, float] VEC4_ZERO = (0.0, 0.0, 0.0, 0.0) DEFAULT_VEC4 = ("VEC4", {"default": VEC4_ZERO}) VEC_UNARY_OPERATIONS: Mapping[str, Callable[[numpy.ndarray], numpy.ndarray]] = { "Neg": lambda a: -a, "Normalize": lambda a: a / numpy.linalg.norm(a), } VEC_TO_SCALAR_UNARY_OPERATION: Mapping[str, Callable[[numpy.ndarray], float]] = { "Norm": lambda a: numpy.linalg.norm(a).astype(float), } VEC_UNARY_CONDITIONS: Mapping[str, Callable[[numpy.ndarray], bool]] = { "IsZero": lambda a: not numpy.any(a).astype(bool), "IsNotZero": lambda a: numpy.any(a).astype(bool), "IsNormalized": lambda a: numpy.allclose(a, a / numpy.linalg.norm(a)), "IsNotNormalized": lambda a: not numpy.allclose(a, a / numpy.linalg.norm(a)), } VEC_BINARY_OPERATIONS: Mapping[ str, Callable[[numpy.ndarray, numpy.ndarray], numpy.ndarray] ] = { "Add": lambda a, b: a + b, "Sub": lambda a, b: a - b, "Cross": lambda a, b: numpy.cross(a, b), } VEC_TO_SCALAR_BINARY_OPERATION: Mapping[ str, Callable[[numpy.ndarray, numpy.ndarray], float] ] = { "Dot": lambda a, b: numpy.dot(a, b), "Distance": lambda a, b: numpy.linalg.norm(a - b).astype(float), } VEC_BINARY_CONDITIONS: Mapping[str, Callable[[numpy.ndarray, numpy.ndarray], bool]] = { "Eq": lambda a, b: numpy.allclose(a, b), "Neq": lambda a, b: not numpy.allclose(a, b), } VEC_SCALAR_OPERATION: Mapping[str, Callable[[numpy.ndarray, float], numpy.ndarray]] = { "Mul": lambda a, b: a * b, "Div": lambda a, b: a / b, } def _vec2_from_numpy(a: numpy.ndarray) -> Vec2: return ( float(a[0]), float(a[1]), ) def _vec3_from_numpy(a: numpy.ndarray) -> Vec3: return ( float(a[0]), float(a[1]), float(a[2]), ) def _vec4_from_numpy(a: numpy.ndarray) -> Vec4: return ( float(a[0]), float(a[1]), float(a[2]), float(a[3]), ) class Vec2UnaryOperation: @classmethod def INPUT_TYPES(cls) -> Mapping[str, Any]: return { "required": { "op": (list(VEC_UNARY_OPERATIONS.keys()),), "a": DEFAULT_VEC2, } } RETURN_TYPES = ("VEC2",) FUNCTION = "op" CATEGORY = "math/vec2" def op(self, op: str, a: Vec2) -> tuple[Vec2]: return (_vec2_from_numpy(VEC_UNARY_OPERATIONS[op](numpy.array(a))),) class Vec2ToScalarUnaryOperation: @classmethod def INPUT_TYPES(cls) -> Mapping[str, Any]: return { "required": { "op": (list(VEC_TO_SCALAR_UNARY_OPERATION.keys()),), "a": DEFAULT_VEC2, } } RETURN_TYPES = ("FLOAT",) FUNCTION = "op" CATEGORY = "math/vec2" def op(self, op: str, a: Vec2) -> tuple[float]: return (VEC_TO_SCALAR_UNARY_OPERATION[op](numpy.array(a)),) class Vec2UnaryCondition: @classmethod def INPUT_TYPES(cls) -> Mapping[str, Any]: return { "required": { "op": (list(VEC_UNARY_CONDITIONS.keys()),), "a": DEFAULT_VEC2, } } RETURN_TYPES = ("BOOL",) FUNCTION = "op" CATEGORY = "math/vec2" def op(self, op: str, a: Vec2) -> tuple[bool]: return (VEC_UNARY_CONDITIONS[op](numpy.array(a)),) class Vec2BinaryOperation: @classmethod def INPUT_TYPES(cls) -> Mapping[str, Any]: return { "required": { "op": (list(VEC_BINARY_OPERATIONS.keys()),), "a": DEFAULT_VEC2, "b": DEFAULT_VEC2, } } RETURN_TYPES = ("VEC2",) FUNCTION = "op" CATEGORY = "math/vec2" def op(self, op: str, a: Vec2, b: Vec2) -> tuple[Vec2]: return ( _vec2_from_numpy(VEC_BINARY_OPERATIONS[op](numpy.array(a), numpy.array(b))), ) class Vec2ToScalarBinaryOperation: @classmethod def INPUT_TYPES(cls) -> Mapping[str, Any]: return { "required": { "op": (list(VEC_TO_SCALAR_BINARY_OPERATION.keys()),), "a": DEFAULT_VEC2, "b": DEFAULT_VEC2, } } RETURN_TYPES = ("FLOAT",) FUNCTION = "op" CATEGORY = "math/vec2" def op(self, op: str, a: Vec2, b: Vec2) -> tuple[float]: return (VEC_TO_SCALAR_BINARY_OPERATION[op](numpy.array(a), numpy.array(b)),) class Vec2BinaryCondition: @classmethod def INPUT_TYPES(cls) -> Mapping[str, Any]: return { "required": { "op": (list(VEC_BINARY_CONDITIONS.keys()),), "a": DEFAULT_VEC2, "b": DEFAULT_VEC2, } } RETURN_TYPES = ("BOOL",) FUNCTION = "op" CATEGORY = "math/vec2" def op(self, op: str, a: Vec2, b: Vec2) -> tuple[bool]: return (VEC_BINARY_CONDITIONS[op](numpy.array(a), numpy.array(b)),) class Vec2ScalarOperation: @classmethod def INPUT_TYPES(cls) -> Mapping[str, Any]: return { "required": { "op": (list(VEC_SCALAR_OPERATION.keys()),), "a": DEFAULT_VEC2, "b": ("FLOAT",), } } RETURN_TYPES = ("VEC2",) FUNCTION = "op" CATEGORY = "math/vec2" def op(self, op: str, a: Vec2, b: float) -> tuple[Vec2]: return (_vec2_from_numpy(VEC_SCALAR_OPERATION[op](numpy.array(a), b)),) class Vec3UnaryOperation: @classmethod def INPUT_TYPES(cls) -> Mapping[str, Any]: return { "required": { "op": (list(VEC_UNARY_OPERATIONS.keys()),), "a": DEFAULT_VEC3, } } RETURN_TYPES = ("VEC3",) FUNCTION = "op" CATEGORY = "math/vec3" def op(self, op: str, a: Vec3) -> tuple[Vec3]: return (_vec3_from_numpy(VEC_UNARY_OPERATIONS[op](numpy.array(a))),) class Vec3ToScalarUnaryOperation: @classmethod def INPUT_TYPES(cls) -> Mapping[str, Any]: return { "required": { "op": (list(VEC_TO_SCALAR_UNARY_OPERATION.keys()),), "a": DEFAULT_VEC3, } } RETURN_TYPES = ("FLOAT",) FUNCTION = "op" CATEGORY = "math/vec3" def op(self, op: str, a: Vec3) -> tuple[float]: return (VEC_TO_SCALAR_UNARY_OPERATION[op](numpy.array(a)),) class Vec3UnaryCondition: @classmethod def INPUT_TYPES(cls) -> Mapping[str, Any]: return { "required": { "op": (list(VEC_UNARY_CONDITIONS.keys()),), "a": DEFAULT_VEC3, } } RETURN_TYPES = ("BOOL",) FUNCTION = "op" CATEGORY = "math/vec3" def op(self, op: str, a: Vec3) -> tuple[bool]: return (VEC_UNARY_CONDITIONS[op](numpy.array(a)),) class Vec3BinaryOperation: @classmethod def INPUT_TYPES(cls) -> Mapping[str, Any]: return { "required": { "op": (list(VEC_BINARY_OPERATIONS.keys()),), "a": DEFAULT_VEC3, "b": DEFAULT_VEC3, } } RETURN_TYPES = ("VEC3",) FUNCTION = "op" CATEGORY = "math/vec3" def op(self, op: str, a: Vec3, b: Vec3) -> tuple[Vec3]: return ( _vec3_from_numpy(VEC_BINARY_OPERATIONS[op](numpy.array(a), numpy.array(b))), ) class Vec3ToScalarBinaryOperation: @classmethod def INPUT_TYPES(cls) -> Mapping[str, Any]: return { "required": { "op": (list(VEC_TO_SCALAR_BINARY_OPERATION.keys()),), "a": DEFAULT_VEC3, "b": DEFAULT_VEC3, } } RETURN_TYPES = ("FLOAT",) FUNCTION = "op" CATEGORY = "math/vec3" def op(self, op: str, a: Vec3, b: Vec3) -> tuple[float]: return (VEC_TO_SCALAR_BINARY_OPERATION[op](numpy.array(a), numpy.array(b)),) class Vec3BinaryCondition: @classmethod def INPUT_TYPES(cls) -> Mapping[str, Any]: return { "required": { "op": (list(VEC_BINARY_CONDITIONS.keys()),), "a": DEFAULT_VEC3, "b": DEFAULT_VEC3, } } RETURN_TYPES = ("BOOL",) FUNCTION = "op" CATEGORY = "math/vec3" def op(self, op: str, a: Vec3, b: Vec3) -> tuple[bool]: return (VEC_BINARY_CONDITIONS[op](numpy.array(a), numpy.array(b)),) class Vec3ScalarOperation: @classmethod def INPUT_TYPES(cls) -> Mapping[str, Any]: return { "required": { "op": (list(VEC_SCALAR_OPERATION.keys()),), "a": DEFAULT_VEC3, "b": ("FLOAT",), } } RETURN_TYPES = ("VEC3",) FUNCTION = "op" CATEGORY = "math/vec3" def op(self, op: str, a: Vec3, b: float) -> tuple[Vec3]: return (_vec3_from_numpy(VEC_SCALAR_OPERATION[op](numpy.array(a), b)),) class Vec4UnaryOperation: @classmethod def INPUT_TYPES(cls) -> Mapping[str, Any]: return { "required": { "op": (list(VEC_UNARY_OPERATIONS.keys()),), "a": DEFAULT_VEC4, } } RETURN_TYPES = ("VEC4",) FUNCTION = "op" CATEGORY = "math/vec4" def op(self, op: str, a: Vec4) -> tuple[Vec4]: return (_vec4_from_numpy(VEC_UNARY_OPERATIONS[op](numpy.array(a))),) class Vec4ToScalarUnaryOperation: @classmethod def INPUT_TYPES(cls) -> Mapping[str, Any]: return { "required": { "op": (list(VEC_TO_SCALAR_UNARY_OPERATION.keys()),), "a": DEFAULT_VEC4, } } RETURN_TYPES = ("FLOAT",) FUNCTION = "op" CATEGORY = "math/vec4" def op(self, op: str, a: Vec4) -> tuple[float]: return (VEC_TO_SCALAR_UNARY_OPERATION[op](numpy.array(a)),) class Vec4UnaryCondition: @classmethod def INPUT_TYPES(cls) -> Mapping[str, Any]: return { "required": { "op": (list(VEC_UNARY_CONDITIONS.keys()),), "a": DEFAULT_VEC4, } } RETURN_TYPES = ("BOOL",) FUNCTION = "op" CATEGORY = "math/vec4" def op(self, op: str, a: Vec4) -> tuple[bool]: return (VEC_UNARY_CONDITIONS[op](numpy.array(a)),) class Vec4BinaryOperation: @classmethod def INPUT_TYPES(cls) -> Mapping[str, Any]: return { "required": { "op": (list(VEC_BINARY_OPERATIONS.keys()),), "a": DEFAULT_VEC4, "b": DEFAULT_VEC4, } } RETURN_TYPES = ("VEC4",) FUNCTION = "op" CATEGORY = "math/vec4" def op(self, op: str, a: Vec4, b: Vec4) -> tuple[Vec4]: return ( _vec4_from_numpy(VEC_BINARY_OPERATIONS[op](numpy.array(a), numpy.array(b))), ) class Vec4ToScalarBinaryOperation: @classmethod def INPUT_TYPES(cls) -> Mapping[str, Any]: return { "required": { "op": (list(VEC_TO_SCALAR_BINARY_OPERATION.keys()),), "a": DEFAULT_VEC4, "b": DEFAULT_VEC4, } } RETURN_TYPES = ("FLOAT",) FUNCTION = "op" CATEGORY = "math/vec4" def op(self, op: str, a: Vec4, b: Vec4) -> tuple[float]: return (VEC_TO_SCALAR_BINARY_OPERATION[op](numpy.array(a), numpy.array(b)),) class Vec4BinaryCondition: @classmethod def INPUT_TYPES(cls) -> Mapping[str, Any]: return { "required": { "op": (list(VEC_BINARY_CONDITIONS.keys()),), "a": DEFAULT_VEC4, "b": DEFAULT_VEC4, } } RETURN_TYPES = ("BOOL",) FUNCTION = "op" CATEGORY = "math/vec4" def op(self, op: str, a: Vec4, b: Vec4) -> tuple[bool]: return (VEC_BINARY_CONDITIONS[op](numpy.array(a), numpy.array(b)),) class Vec4ScalarOperation: @classmethod def INPUT_TYPES(cls) -> Mapping[str, Any]: return { "required": { "op": (list(VEC_SCALAR_OPERATION.keys()),), "a": DEFAULT_VEC4, "b": ("FLOAT",), } } RETURN_TYPES = ("VEC4",) FUNCTION = "op" CATEGORY = "math/vec4" def op(self, op: str, a: Vec4, b: float) -> tuple[Vec4]: return (_vec4_from_numpy(VEC_SCALAR_OPERATION[op](numpy.array(a), b)),) NODE_CLASS_MAPPINGS = { "CM_Vec2UnaryOperation": Vec2UnaryOperation, "CM_Vec2UnaryCondition": Vec2UnaryCondition, "CM_Vec2ToScalarUnaryOperation": Vec2ToScalarUnaryOperation, "CM_Vec2BinaryOperation": Vec2BinaryOperation, "CM_Vec2BinaryCondition": Vec2BinaryCondition, "CM_Vec2ToScalarBinaryOperation": Vec2ToScalarBinaryOperation, "CM_Vec2ScalarOperation": Vec2ScalarOperation, "CM_Vec3UnaryOperation": Vec3UnaryOperation, "CM_Vec3UnaryCondition": Vec3UnaryCondition, "CM_Vec3ToScalarUnaryOperation": Vec3ToScalarUnaryOperation, "CM_Vec3BinaryOperation": Vec3BinaryOperation, "CM_Vec3BinaryCondition": Vec3BinaryCondition, "CM_Vec3ToScalarBinaryOperation": Vec3ToScalarBinaryOperation, "CM_Vec3ScalarOperation": Vec3ScalarOperation, "CM_Vec4UnaryOperation": Vec4UnaryOperation, "CM_Vec4UnaryCondition": Vec4UnaryCondition, "CM_Vec4ToScalarUnaryOperation": Vec4ToScalarUnaryOperation, "CM_Vec4BinaryOperation": Vec4BinaryOperation, "CM_Vec4BinaryCondition": Vec4BinaryCondition, "CM_Vec4ToScalarBinaryOperation": Vec4ToScalarBinaryOperation, "CM_Vec4ScalarOperation": Vec4ScalarOperation, }