math_nodes.py 5.3 KB

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