|
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,
|
|
}
|
|
|