xForm_definitions.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. import bpy
  2. from .base_definitions import xFormNode
  3. from bpy.types import Node
  4. from .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 ('BoneCollectionInputSocket', "Bone Collection"))
  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. # 16-21
  97. # Deform Settings:
  98. c = []
  99. c.append(self.inputs.new ('BooleanSocket', "Deform"))
  100. c.append(self.inputs.new ('FloatPositiveSocket', "Envelope Distance"))
  101. c.append(self.inputs.new ('FloatFactorSocket', "Envelope Weight"))
  102. c.append(self.inputs.new ('BooleanSocket', "Envelope Multiply"))
  103. c.append(self.inputs.new ('FloatPositiveSocket', "Envelope Head Radius"))
  104. c.append(self.inputs.new ('FloatPositiveSocket', "Envelope Tail Radius"))
  105. #22-27
  106. # c[0].default_value=False
  107. # Hide should be last
  108. b.append(self.inputs.new ('HideSocket', "Hide"))
  109. for sock in a:
  110. sock.hide = True
  111. for sock in b:
  112. if sock.name in ['Custom Object', 'Bone Collection']:
  113. continue
  114. sock.hide = True
  115. for sock in c:
  116. if sock.name == 'Deform':
  117. continue
  118. sock.hide = True
  119. # Thinking about using colors for nodes, why not?
  120. # cxForm = (0.443137, 0.242157, 0.188235,) #could even fetch the theme colors...
  121. # self.color=cxForm
  122. # self.use_custom_color=True
  123. self.socket_count = len(self.inputs)
  124. #
  125. self.outputs.new('xFormSocket', "xForm Out")
  126. def draw_buttons(self, context, layout):
  127. layout.operator("mantis.add_custom_property", text='+Add Custom Parameter')
  128. # layout.label(text="Edit Parameter ... not implemented")
  129. if (len(self.inputs) > self.socket_count):
  130. layout.operator("mantis.remove_custom_property", text='-Remove Custom Parameter')
  131. else:
  132. layout.label(text="")
  133. def display_update(self, parsed_tree, context):
  134. if context.space_data:
  135. node_tree = context.space_data.path[0].node_tree
  136. nc = parsed_tree.get(get_signature_from_edited_tree(self, context))
  137. other_nc = None
  138. if len(self.inputs.get("Relationship").links)>0:
  139. prev_node = self.inputs.get("Relationship").links[0].from_node
  140. if prev_node:
  141. other_nc = parsed_tree.get(get_signature_from_edited_tree(prev_node, context))
  142. if nc and other_nc:
  143. self.display_vp_settings = nc.inputs["Custom Object"].is_connected
  144. self.display_def_settings = nc.evaluate_input("Deform")
  145. self.display_ik_settings = False
  146. #
  147. from .node_container_common import ( trace_all_lines_up,
  148. trace_single_line)
  149. trace = trace_all_lines_up(nc, "xForm Out")
  150. for key in trace.keys():
  151. if (ik_nc:= parsed_tree.get(key)):
  152. if ik_nc.__class__.__name__ in ["LinkInverseKinematics"]:
  153. # if the tree is invalid? This shouldn't be necessary.
  154. if ik_nc.inputs["Input Relationship"].is_connected:
  155. chain_count = ik_nc.evaluate_input("Chain Length")
  156. if chain_count == 0:
  157. self.display_ik_settings = True
  158. else:
  159. if ik_nc.evaluate_input("Use Tail") == False:
  160. chain_count+=1
  161. for line in trace[key]:
  162. # preprocess it to get rid of non-xForms:
  163. xForm_line=[]
  164. for path_nc in line:
  165. if path_nc == ik_nc:
  166. if ik_nc.inputs["Input Relationship"].links[0].from_node != prev_path_nc:
  167. break # not a constraint connection
  168. if path_nc.node_type == 'XFORM':
  169. xForm_line.append(path_nc)
  170. prev_path_nc = path_nc
  171. else:
  172. if len(xForm_line) < chain_count:
  173. self.display_ik_settings = True
  174. inp = nc.inputs["Relationship"]
  175. link = None
  176. if inp.is_connected:
  177. link = inp.links[0]
  178. while(link):
  179. if link.from_node.__class__.__name__ in ["LinkInverseKinematics"]:
  180. self.display_ik_settings = link.from_node.evaluate_input("Use Tail")
  181. break
  182. inp = link.from_node.outputs[link.from_socket]
  183. inp = inp.traverse_target
  184. if not inp:
  185. break
  186. if inp.links:
  187. link = inp.links[0]
  188. else:
  189. link = None
  190. #
  191. if self.display_ik_settings == True:
  192. for inp in self.inputs[4:14]:
  193. inp.hide = False
  194. else:
  195. for inp in self.inputs[4:14]:
  196. inp.hide = True
  197. if self.display_vp_settings == True:
  198. for inp in self.inputs[16:21]:
  199. inp.hide = False
  200. else:
  201. for inp in self.inputs[16:21]:
  202. inp.hide = True
  203. #
  204. if self.display_def_settings == True:
  205. for inp in self.inputs[23:28]:
  206. inp.hide = False
  207. else:
  208. for inp in self.inputs[23:28]:
  209. inp.hide = True
  210. # def copy(ectype, archtype):
  211. # # TODO: automatically avoid duplicating names
  212. # ectype.inputs["Name"].default_value = ""
  213. class xFormArmatureNode(Node, xFormNode):
  214. '''A node representing an Armature object node'''
  215. bl_idname = 'xFormArmatureNode'
  216. bl_label = "Armature"
  217. bl_icon = 'OUTLINER_OB_ARMATURE'
  218. def init(self, context):
  219. self.inputs.new('StringSocket', "Name")
  220. self.inputs.new('RelationshipSocket', "Relationship")
  221. self.inputs.new('RotationOrderSocket', "Rotation Order")
  222. self.inputs.new('MatrixSocket', "Matrix")
  223. self.outputs.new('xFormSocket', "xForm Out")
  224. class xFormGeometryObjectNode(Node, xFormNode):
  225. """Represents a curve or mesh object."""
  226. bl_idname = "xFormGeometryObject"
  227. bl_label = "Geometry Object"
  228. bl_icon = "EMPTY_AXIS"
  229. def init(self, context):
  230. self.inputs.new('StringSocket', "Name")
  231. self.inputs.new('GeometrySocket', "Geometry")
  232. self.inputs.new('MatrixSocket', "Matrix")
  233. self.inputs.new('RelationshipSocket', "Relationship")
  234. self.outputs.new('xFormSocket', "xForm Out")