math_nodes.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. from .utilities.node_common import *
  2. from .base_definitions import MantisNode
  3. from .math_nodes_socket_templates import *
  4. def TellClasses():
  5. return [
  6. MathStaticInt,
  7. MathStaticFloat,
  8. MathStaticVector,
  9. ]
  10. def math_operation(operation, a, b):
  11. match operation:
  12. case "ADD":
  13. return a+b
  14. case "SUBTRACT":
  15. return a-b
  16. case "MULTIPLY":
  17. return a*b
  18. case "DIVIDE":
  19. return a/b
  20. case "FLOOR_DIVIDE":
  21. return a//b
  22. case "MODULUS":
  23. return a%b
  24. case "POWER":
  25. return a**b
  26. case "ABSOLUTE":
  27. return abs(a)
  28. case "MAXIMUM":
  29. return max(a, b)
  30. case "MINIMUM":
  31. return min(a, b)
  32. case "GREATER THAN":
  33. return float(a > b)
  34. case "LESS THAN":
  35. return float(a < b)
  36. case "ARCTAN2":
  37. from math import atan2
  38. return atan2(a,b)
  39. case "FLOOR":
  40. from math import floor
  41. return floor(a)
  42. case "CEIL":
  43. from math import ceil
  44. return ceil(a)
  45. case "ROUND":
  46. return round(a)
  47. #*#-------------------------------#++#-------------------------------#*#
  48. # M A T H N O D E S
  49. #*#-------------------------------#++#-------------------------------#*#
  50. class MathStaticInt(MantisNode):
  51. '''A node representing an integer math operation'''
  52. __slots__ = ()
  53. node_type = "UTILITY"
  54. def __init__(self, signature, base_tree):
  55. super().__init__(signature, base_tree, StaticIntSockets)
  56. self.init_parameters()
  57. def bPrepare(self, bContext = None,):
  58. a = self.evaluate_input("Int A"); b = self.evaluate_input("Int B")
  59. result = math_operation(self.evaluate_input("Operation"), a, b)
  60. self.parameters["Result Int"] = int(result)
  61. self.prepared, self.executed = True, True
  62. class MathStaticFloat(MantisNode):
  63. '''A node representing a float math operation'''
  64. __slots__ = ()
  65. node_type = "UTILITY"
  66. def __init__(self, signature, base_tree):
  67. super().__init__(signature, base_tree, StaticFloatSockets)
  68. self.init_parameters()
  69. def bPrepare(self, bContext = None,):
  70. a = self.evaluate_input("Float A"); b = self.evaluate_input("Float B")
  71. result = math_operation(self.evaluate_input("Operation"), a, b)
  72. self.parameters["Result Float"] = result
  73. self.prepared, self.executed = True, True
  74. class MathStaticVector(MantisNode):
  75. '''A node representing a vector math operation'''
  76. __slots__ = ()
  77. node_type = "UTILITY"
  78. def __init__(self, signature, base_tree):
  79. super().__init__(signature, base_tree, StaticVectorSockets)
  80. self.init_parameters()
  81. def bPrepare(self, bContext = None,):
  82. from mathutils import Vector
  83. a = Vector(self.evaluate_input("Vector A")).copy()
  84. b = Vector(self.evaluate_input("Vector B")).copy()
  85. s = self.evaluate_input("Scalar A")
  86. if hasattr(s, '__iter__'):
  87. average = lambda iterable : sum(iterable)/len(iterable)
  88. s = average(s)
  89. f_result = float("NaN")
  90. v_result = None
  91. if self.evaluate_input("Operation") == "ADD":
  92. v_result = a+b
  93. if self.evaluate_input("Operation") == "SUBTRACT":
  94. v_result = a-b
  95. if self.evaluate_input("Operation") == "MULTIPLY":
  96. v_result = a*b
  97. if self.evaluate_input("Operation") == "DIVIDE":
  98. v_result = Vector((0,0,0)) # channel-wise division
  99. for i, (axis_a, axis_b) in enumerate(zip(a,b)):
  100. v_result[i] = axis_a/axis_b
  101. if self.evaluate_input("Operation") == "POWER":
  102. v_result = a**b
  103. # since these are unary, we need to make a copy lest we create spooky effects elsewhere.
  104. a = a.copy()
  105. if self.evaluate_input("Operation") == "SCALE":
  106. v_result = a.normalized() * s
  107. if self.evaluate_input("Operation") == "LENGTH":
  108. f_result = a.magnitude
  109. if self.evaluate_input("Operation") == "CROSS":
  110. v_result = a.cross(b)
  111. if self.evaluate_input("Operation") == "DOT":
  112. f_result = a.dot(b)
  113. if self.evaluate_input("Operation") == "NORMALIZE":
  114. v_result = a.normalized()
  115. if self.evaluate_input("Operation") == "LINEAR_INTERP":
  116. v_result = a.lerp(b, s).copy()
  117. self.parameters["Result Float"] = f_result
  118. # if v_result:
  119. self.parameters["Result Vector"] = v_result
  120. self.prepared = True
  121. self.executed = True