xForm_definitions.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. import bpy
  2. from .base_definitions import xFormNode
  3. from bpy.types import Node
  4. from mantis.utilities import (prRed, prGreen, prPurple, prWhite,
  5. prOrange,
  6. wrapRed, wrapGreen, wrapPurple, wrapWhite,
  7. wrapOrange,)
  8. from .base_definitions import get_signature_from_edited_tree
  9. def TellClasses():
  10. return [
  11. # xFormNullNode,
  12. xFormBoneNode,
  13. xFormRootNode,
  14. xFormArmatureNode,
  15. xFormGeometryObjectNode,
  16. ]
  17. def default_traverse(self, socket):
  18. if (socket == self.outputs["xForm Out"]):
  19. return self.inputs["Relationship"]
  20. if (socket == self.inputs["Relationship"]):
  21. return self.outputs["xForm Out"]
  22. return None
  23. # Representing an Empty or non-armature-Object
  24. # class xFormNullNode(Node, xFormNode):
  25. # '''A node representing a Null node'''
  26. # bl_idname = 'xFormNullNode'
  27. # bl_label = "Null"
  28. # bl_icon = 'EMPTY_AXIS'
  29. # # === Optional Functions ===
  30. # def init(self, context):
  31. # self.inputs.new('StringSocket', "Name")
  32. # self.inputs.new('RelationshipSocket', "Relationship")
  33. # self.inputs.new('RotationOrderSocket', "Rotation Order")
  34. # self.inputs.new('MatrixSocket', "Matrix")
  35. # self.outputs.new('xFormSocket', "xForm Out")
  36. def check_if_connected(start, end, line):
  37. started=False
  38. for path_nc in line:
  39. prWhite(" ", path_nc.signature)
  40. if path_nc.signature == start.signature:
  41. started = True
  42. elif path_nc.signature == end.signature:
  43. break
  44. if started:
  45. if path_nc.inputs.get("Connected"):
  46. if path_nc.evaluate_input("Connected") == False:
  47. return False
  48. else:
  49. return False
  50. return True
  51. class xFormRootNode(Node, xFormNode):
  52. '''A node representing the world node'''
  53. bl_idname = 'xFormRootNode'
  54. bl_label = "World Root"
  55. bl_icon = 'WORLD'
  56. def init(self, context):
  57. self.outputs.new('RelationshipSocket', "World Out")
  58. class xFormBoneNode(Node, xFormNode):
  59. '''A node representing a Bone'''
  60. bl_idname = 'xFormBoneNode'
  61. bl_label = "Bone"
  62. bl_icon = 'BONE_DATA'
  63. display_ik_settings : bpy.props.BoolProperty(default=False)
  64. display_vp_settings : bpy.props.BoolProperty(default=False)
  65. display_def_settings : bpy.props.BoolProperty(default=False)
  66. socket_count : bpy.props.IntProperty()
  67. def init(self, context):
  68. self.inputs.new('StringSocket', "Name")
  69. self.inputs.new('RotationOrderSocket', "Rotation Order")
  70. self.inputs.new('RelationshipSocket', "Relationship")
  71. self.inputs.new('MatrixSocket', "Matrix")
  72. # IK SETTINGS
  73. a = []
  74. # a.append(self.inputs.new ('LabelSocket', "IK Settings"))
  75. a.append(self.inputs.new ('FloatFactorSocket', "IK Stretch"))
  76. a.append(self.inputs.new ('BooleanThreeTupleSocket', "Lock IK"))
  77. a.append(self.inputs.new ('NodeSocketVector', "IK Stiffness"))
  78. a.append(self.inputs.new ('BooleanThreeTupleSocket', "Limit IK"))
  79. a.append(self.inputs.new ('NodeSocketFloatAngle', "X Min"))
  80. a.append(self.inputs.new ('NodeSocketFloatAngle', "X Max"))
  81. a.append(self.inputs.new ('NodeSocketFloatAngle', "Y Min"))
  82. a.append(self.inputs.new ('NodeSocketFloatAngle', "Y Max"))
  83. a.append(self.inputs.new ('NodeSocketFloatAngle', "Z Min"))
  84. a.append(self.inputs.new ('NodeSocketFloatAngle', "Z Max"))
  85. #4-14
  86. # visual settings:
  87. b = []
  88. b.append(self.inputs.new ('LayerMaskSocket', "Layer Mask"))
  89. b.append(self.inputs.new ('xFormSocket', "Custom Object"))
  90. b.append(self.inputs.new ('xFormSocket', "Custom Object xForm Override"))
  91. b.append(self.inputs.new ('BooleanSocket', "Custom Object Scale to Bone Length"))
  92. b.append(self.inputs.new ('BooleanSocket', "Custom Object Wireframe"))
  93. b.append(self.inputs.new ('VectorScaleSocket', "Custom Object Scale"))
  94. b.append(self.inputs.new ('VectorSocket', "Custom Object Translation"))
  95. b.append(self.inputs.new ('VectorEulerSocket', "Custom Object Rotation"))
  96. b.append(self.inputs.new ('StringSocket', "Bone Group"))
  97. # 16-22
  98. # Deform Settings:
  99. c = []
  100. c.append(self.inputs.new ('BooleanSocket', "Deform"))
  101. c.append(self.inputs.new ('FloatPositiveSocket', "Envelope Distance"))
  102. c.append(self.inputs.new ('FloatFactorSocket', "Envelope Weight"))
  103. c.append(self.inputs.new ('BooleanSocket', "Envelope Multiply"))
  104. c.append(self.inputs.new ('FloatPositiveSocket', "Envelope Head Radius"))
  105. c.append(self.inputs.new ('FloatPositiveSocket', "Envelope Tail Radius"))
  106. #24-28
  107. # c[0].default_value=False
  108. # Hide should be last
  109. b.append(self.inputs.new ('HideSocket', "Hide"))
  110. for sock in a:
  111. sock.hide = True
  112. for sock in b:
  113. if sock.name in ['Custom Object', 'Layer Mask']:
  114. continue
  115. sock.hide = True
  116. for sock in c:
  117. if sock.name == 'Deform':
  118. continue
  119. sock.hide = True
  120. # Thinking about using colors for nodes, why not?
  121. # cxForm = (0.443137, 0.242157, 0.188235,) #could even fetch the theme colors...
  122. # self.color=cxForm
  123. # self.use_custom_color=True
  124. self.socket_count = len(self.inputs)
  125. #
  126. self.outputs.new('xFormSocket', "xForm Out")
  127. def draw_buttons(self, context, layout):
  128. layout.operator("mantis.add_custom_property", text='+Add Custom Parameter')
  129. # layout.label(text="Edit Parameter ... not implemented")
  130. if (len(self.inputs) > self.socket_count):
  131. layout.operator("mantis.remove_custom_property", text='-Remove Custom Parameter')
  132. else:
  133. layout.label(text="")
  134. def display_update(self, parsed_tree, context):
  135. if context.space_data:
  136. node_tree = context.space_data.path[0].node_tree
  137. nc = parsed_tree.get(get_signature_from_edited_tree(self, context))
  138. other_nc = None
  139. if len(self.inputs.get("Relationship").links)>0:
  140. prev_node = self.inputs.get("Relationship").links[0].from_node
  141. if prev_node:
  142. other_nc = parsed_tree.get(get_signature_from_edited_tree(prev_node, context))
  143. if nc and other_nc:
  144. self.display_vp_settings = nc.inputs["Custom Object"].is_connected
  145. self.display_def_settings = nc.evaluate_input("Deform")
  146. self.display_ik_settings = False
  147. #
  148. from .node_container_common import ( trace_all_lines_up,
  149. trace_single_line)
  150. trace = trace_all_lines_up(nc, "xForm Out")
  151. for key in trace.keys():
  152. if (ik_nc:= parsed_tree.get(key)):
  153. if ik_nc.__class__.__name__ in ["LinkInverseKinematics"]:
  154. # if the tree is invalid? This shouldn't be necessary.
  155. if ik_nc.inputs["Input Relationship"].is_connected:
  156. chain_count = ik_nc.evaluate_input("Chain Length")
  157. if chain_count == 0:
  158. self.display_ik_settings = True
  159. else:
  160. if ik_nc.evaluate_input("Use Tail") == False:
  161. chain_count+=1
  162. for line in trace[key]:
  163. # preprocess it to get rid of non-xForms:
  164. xForm_line=[]
  165. for path_nc in line:
  166. if path_nc == ik_nc:
  167. if ik_nc.inputs["Input Relationship"].links[0].from_node != prev_path_nc:
  168. break # not a constraint connection
  169. if path_nc.node_type == 'XFORM':
  170. xForm_line.append(path_nc)
  171. prev_path_nc = path_nc
  172. else:
  173. if len(xForm_line) < chain_count:
  174. self.display_ik_settings = True
  175. inp = nc.inputs["Relationship"]
  176. link = None
  177. if inp.is_connected:
  178. link = inp.links[0]
  179. while(link):
  180. if link.from_node.__class__.__name__ in ["LinkInverseKinematics"]:
  181. self.display_ik_settings = link.from_node.evaluate_input("Use Tail")
  182. break
  183. inp = link.from_node.outputs[link.from_socket]
  184. inp = inp.traverse_target
  185. if not inp:
  186. break
  187. if inp.links:
  188. link = inp.links[0]
  189. else:
  190. link = None
  191. #
  192. if self.display_ik_settings == True:
  193. for inp in self.inputs[4:14]:
  194. inp.hide = False
  195. else:
  196. for inp in self.inputs[4:14]:
  197. inp.hide = True
  198. if self.display_vp_settings == True:
  199. for inp in self.inputs[16:22]:
  200. inp.hide = False
  201. else:
  202. for inp in self.inputs[16:22]:
  203. inp.hide = True
  204. #
  205. if self.display_def_settings == True:
  206. for inp in self.inputs[24:29]:
  207. inp.hide = False
  208. else:
  209. for inp in self.inputs[24:29]:
  210. inp.hide = True
  211. # def copy(ectype, archtype):
  212. # # TODO: automatically avoid duplicating names
  213. # ectype.inputs["Name"].default_value = ""
  214. class xFormArmatureNode(Node, xFormNode):
  215. '''A node representing an Armature object node'''
  216. bl_idname = 'xFormArmatureNode'
  217. bl_label = "Armature"
  218. bl_icon = 'OUTLINER_OB_ARMATURE'
  219. def init(self, context):
  220. self.inputs.new('StringSocket', "Name")
  221. self.inputs.new('RelationshipSocket', "Relationship")
  222. self.inputs.new('RotationOrderSocket', "Rotation Order")
  223. self.inputs.new('MatrixSocket', "Matrix")
  224. self.outputs.new('xFormSocket', "xForm Out")
  225. class xFormGeometryObjectNode(Node, xFormNode):
  226. """Represents a curve or mesh object."""
  227. bl_idname = "xFormGeometryObject"
  228. bl_label = "Geometry Object"
  229. bl_icon = "EMPTY_AXIS"
  230. def init(self, context):
  231. self.inputs.new('StringSocket', "Name")
  232. self.inputs.new('GeometrySocket', "Geometry")
  233. self.inputs.new('MatrixSocket', "Matrix")
  234. self.inputs.new('RelationshipSocket', "Relationship")
  235. self.outputs.new('xFormSocket', "xForm Out")