link_definitions.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. import bpy
  2. from bpy.types import NodeTree, Node, NodeSocket
  3. from .base_definitions import LinkNode, GraphError
  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. from .link_socket_templates import *
  10. def TellClasses():
  11. return [ LinkInheritNode,
  12. LinkInverseKinematics,
  13. LinkCopyLocationNode,
  14. LinkCopyRotationNode,
  15. LinkCopyScaleNode,
  16. LinkInheritConstraintNode,
  17. LinkCopyTransformNode,
  18. LinkStretchToNode,
  19. LinkDampedTrackNode,
  20. LinkLockedTrackNode,
  21. LinkTrackToNode,
  22. LinkLimitLocationNode,
  23. LinkLimitScaleNode,
  24. LinkLimitRotationNode,
  25. LinkLimitDistanceNode,
  26. LinkDrivenParameterNode,
  27. LinkArmatureNode,
  28. LinkSplineIKNode,
  29. LinkTransformationNode,
  30. ]
  31. from mathutils import Color # these colors were sampled from Blender's UI
  32. # TODO: maybe read the relevant colors from the Theme
  33. linkColor = Color((0.028034, 0.093164, 0.070379)).from_scene_linear_to_srgb()
  34. inheritColor = Color((0.083213, 0.131242, 0.116497)).from_scene_linear_to_srgb()
  35. trackingColor = Color((0.033114, 0.049013, 0.131248)).from_scene_linear_to_srgb()
  36. ikColor = Color((0.131117, 0.131248, 0.006971)).from_scene_linear_to_srgb()
  37. driverColor = Color((0.043782, 0.014745, 0.131248,)).from_scene_linear_to_srgb()
  38. class LinkInheritNode(Node, LinkNode):
  39. '''A node representing inheritance'''
  40. # cuss, messed this up
  41. bl_idname = 'linkInherit' # l should be L
  42. # need to fix this
  43. bl_label = "Inherit"
  44. bl_icon = 'CONSTRAINT_BONE'
  45. initialized : bpy.props.BoolProperty(default = False)
  46. mantis_node_class_name="LinkInherit"
  47. def init(self, context):
  48. self.init_sockets(LinkInheritSockets)
  49. self.initialized = True
  50. self.use_custom_color = True
  51. self.color = inheritColor
  52. def display_update(self, parsed_tree, context):
  53. node_tree = context.space_data.path[0].node_tree
  54. nc = parsed_tree.get(get_signature_from_edited_tree(self, context))
  55. if nc:
  56. bone_prev, bone_next = False, False
  57. if (inp := nc.inputs["Parent"]).is_connected:
  58. if from_node := inp.links[0].from_node:
  59. if from_node.__class__.__name__ in ["xFormBone"]:
  60. bone_prev=True
  61. bone_next=True
  62. try:
  63. xForm = nc.GetxForm()
  64. if xForm.__class__.__name__ not in "xFormBone":
  65. bone_next=False
  66. except GraphError:
  67. bone_next=False
  68. # print(bone_prev, bone_next )
  69. if bone_next and bone_prev:
  70. self.inputs["Inherit Rotation"].hide = False
  71. self.inputs["Inherit Scale"].hide = False
  72. self.inputs["Connected"].hide = False
  73. else:
  74. self.inputs["Inherit Rotation"].hide = True or self.inputs["Inherit Rotation"].is_connected
  75. self.inputs["Inherit Scale"].hide = True or self.inputs["Inherit Scale"].is_connected
  76. self.inputs["Connected"].hide = True or self.inputs["Connected"].is_connected
  77. # the node_groups on the way here ought to be active if there
  78. # is no funny business going on.
  79. # DO: make another node for ITASC IK, eh?
  80. class LinkInverseKinematics(Node, LinkNode):
  81. '''A node representing inverse kinematics'''
  82. bl_idname = 'LinkInverseKinematics'
  83. bl_label = "Inverse Kinematics"
  84. bl_icon = 'CON_KINEMATIC'
  85. initialized : bpy.props.BoolProperty(default = False)
  86. mantis_node_class_name=bl_idname
  87. def init(self, context):
  88. self.init_sockets(LinkInverseKinematicsSockets)
  89. self.initialized = True
  90. self.use_custom_color = True
  91. self.color = ikColor
  92. class LinkCopyLocationNode(Node, LinkNode):
  93. '''A node representing Copy Location'''
  94. bl_idname = 'LinkCopyLocation'
  95. bl_label = "Copy Location"
  96. bl_icon = 'CON_LOCLIKE'
  97. initialized : bpy.props.BoolProperty(default = False)
  98. mantis_node_class_name=bl_idname
  99. def init(self, context):
  100. self.init_sockets(LinkCopyLocationSockets)
  101. self.use_custom_color = True
  102. self.color = linkColor
  103. self.initialized = True
  104. class LinkCopyRotationNode(Node, LinkNode):
  105. '''A node representing Copy Rotation'''
  106. bl_idname = 'LinkCopyRotation'
  107. bl_label = "Copy Rotation"
  108. bl_icon = 'CON_ROTLIKE'
  109. initialized : bpy.props.BoolProperty(default = False)
  110. mantis_node_class_name=bl_idname
  111. def init(self, context):
  112. self.init_sockets(LinkCopyRotationSockets)
  113. self.use_custom_color = True
  114. self.color = linkColor
  115. self.initialized = True
  116. class LinkCopyScaleNode(Node, LinkNode):
  117. '''A node representing Copy Scale'''
  118. bl_idname = 'LinkCopyScale'
  119. bl_label = "Copy Scale"
  120. bl_icon = 'CON_SIZELIKE'
  121. initialized : bpy.props.BoolProperty(default = False)
  122. mantis_node_class_name=bl_idname
  123. def init(self, context):
  124. self.init_sockets(LinkCopyScaleSockets)
  125. self.use_custom_color = True
  126. self.color = linkColor
  127. self.initialized = True
  128. class LinkInheritConstraintNode(Node, LinkNode):
  129. # === Basics ===
  130. # Description string
  131. '''A node representing a parent constraint'''
  132. bl_idname = 'LinkInheritConstraint'
  133. bl_label = "Inherit (constraint)"
  134. bl_icon = 'CON_CHILDOF'
  135. initialized : bpy.props.BoolProperty(default = False)
  136. mantis_node_class_name=bl_idname
  137. # === Optional Functions ===
  138. def init(self, context):
  139. self.init_sockets(LinkInheritConstraintSockets)
  140. self.use_custom_color = True
  141. self.color = inheritColor
  142. self.initialized = True
  143. class LinkCopyTransformNode(Node, LinkNode):
  144. # === Basics ===
  145. # Description string
  146. '''A node representing Copy Transform'''
  147. bl_idname = 'LinkCopyTransforms'
  148. bl_label = "Copy Transform"
  149. bl_icon = 'CON_TRANSLIKE'
  150. initialized : bpy.props.BoolProperty(default = False)
  151. mantis_node_class_name=bl_idname
  152. # === Optional Functions ===
  153. def init(self, context):
  154. self.init_sockets(LinkCopyTransformsSockets)
  155. self.use_custom_color = True
  156. self.color = linkColor
  157. self.initialized = True
  158. class LinkStretchToNode(Node, LinkNode):
  159. '''A node representing Stretch-To'''
  160. bl_idname = 'LinkStretchTo'
  161. bl_label = "Stretch To"
  162. bl_icon = 'CON_STRETCHTO'
  163. initialized : bpy.props.BoolProperty(default = False)
  164. mantis_node_class_name=bl_idname
  165. def init(self, context):
  166. self.init_sockets(LinkStretchToSockets)
  167. self.initialized = True
  168. self.use_custom_color = True
  169. self.color = trackingColor
  170. class LinkDampedTrackNode(Node, LinkNode):
  171. '''A node representing Stretch-To'''
  172. bl_idname = 'LinkDampedTrack'
  173. bl_label = "Damped Track"
  174. bl_icon = 'CON_TRACKTO'
  175. initialized : bpy.props.BoolProperty(default = False)
  176. mantis_node_class_name=bl_idname
  177. def init(self, context):
  178. self.init_sockets(LinkDampedTrackSockets)
  179. self.initialized = True
  180. self.use_custom_color = True
  181. self.color = trackingColor
  182. class LinkLockedTrackNode(Node, LinkNode):
  183. '''A node representing Stretch-To'''
  184. bl_idname = 'LinkLockedTrack'
  185. bl_label = "Locked Track"
  186. bl_icon = 'CON_LOCKTRACK'
  187. initialized : bpy.props.BoolProperty(default = False)
  188. mantis_node_class_name=bl_idname
  189. def init(self, context):
  190. self.init_sockets(LinkLockedTrackSockets)
  191. self.initialized = True
  192. self.use_custom_color = True
  193. self.color = trackingColor
  194. class LinkTrackToNode(Node, LinkNode):
  195. '''A node representing Stretch-To'''
  196. bl_idname = 'LinkTrackTo'
  197. bl_label = "Track To"
  198. bl_icon = 'CON_TRACKTO'
  199. initialized : bpy.props.BoolProperty(default = False)
  200. mantis_node_class_name=bl_idname
  201. def init(self, context):
  202. self.init_sockets(LinkTrackToSockets)
  203. self.initialized = True
  204. self.use_custom_color = True
  205. self.color = trackingColor
  206. class LinkLimitLocationNode(Node, LinkNode):
  207. '''A node representing Limit Location'''
  208. bl_idname = 'LinkLimitLocation'
  209. bl_label = "Limit Location"
  210. bl_icon = 'CON_LOCLIMIT'
  211. mantis_node_class_name=bl_idname
  212. initialized : bpy.props.BoolProperty(default = False)
  213. def init(self, context):
  214. self.init_sockets(LinkLimitLocationScaleSockets)
  215. self.initialized = True
  216. self.use_custom_color = True
  217. self.color = linkColor
  218. class LinkLimitScaleNode(Node, LinkNode):
  219. '''A node representing Limit Scale'''
  220. bl_idname = 'LinkLimitScale'
  221. bl_label = "Limit Scale"
  222. bl_icon = 'CON_SIZELIMIT'
  223. initialized : bpy.props.BoolProperty(default = False)
  224. mantis_node_class_name=bl_idname
  225. def init(self, context):
  226. self.init_sockets(LinkLimitLocationScaleSockets)
  227. self.initialized = True
  228. self.use_custom_color = True
  229. self.color = linkColor
  230. class LinkLimitRotationNode(Node, LinkNode):
  231. '''A node representing Limit Rotation'''
  232. bl_idname = 'LinkLimitRotation'
  233. bl_label = "Limit Rotation"
  234. bl_icon = 'CON_ROTLIMIT'
  235. initialized : bpy.props.BoolProperty(default = False)
  236. mantis_node_class_name=bl_idname
  237. def init(self, context):
  238. self.init_sockets(LinkLimitRotationSockets)
  239. self.initialized = True
  240. # color
  241. self.use_custom_color = True
  242. self.color = linkColor
  243. class LinkLimitDistanceNode(Node, LinkNode):
  244. '''A node representing Limit Distance'''
  245. bl_idname = 'LinkLimitDistance'
  246. bl_label = "Limit Distance"
  247. bl_icon = 'CON_DISTLIMIT'
  248. initialized : bpy.props.BoolProperty(default = False)
  249. mantis_node_class_name=bl_idname
  250. def init(self, context):
  251. self.init_sockets(LinkLimitDistanceSockets)
  252. self.use_custom_color = True
  253. self.color = linkColor
  254. self.initialized = True
  255. class LinkTransformationNode(Node, LinkNode):
  256. '''A node representing Transformation (Constraint)'''
  257. bl_idname = 'LinkTransformation'
  258. bl_label = "Transformation"
  259. bl_icon = 'CON_TRANSFORM'
  260. initialized : bpy.props.BoolProperty(default = False)
  261. mantis_node_class_name=bl_idname
  262. def init(self, context):
  263. self.init_sockets(LinkTransformationSockets)
  264. self.use_custom_color = True
  265. self.color = linkColor
  266. self.initialized = True
  267. def display_update(self, parsed_tree, context):
  268. node_tree = context.space_data.path[0].node_tree
  269. nc = parsed_tree.get(get_signature_from_edited_tree(self, context))
  270. if nc:
  271. if nc.evaluate_input("Map From") == "ROTATION":
  272. self.inputs["Rotation Mode"].hide=False
  273. else:
  274. self.inputs["Rotation Mode"].hide=True
  275. if nc.evaluate_input("Map To") == "TRANSLATION":
  276. self.inputs["Rotation Order"].hide=True
  277. self.inputs["Mix Mode (Translation)"].hide=False
  278. self.inputs["Mix Mode (Rotation)"].hide=True
  279. self.inputs["Mix Mode (Scale)"].hide=True
  280. elif nc.evaluate_input("Map To") == "ROTATION":
  281. self.inputs["Rotation Order"].hide=False
  282. self.inputs["Mix Mode (Translation)"].hide=True
  283. self.inputs["Mix Mode (Rotation)"].hide=False
  284. self.inputs["Mix Mode (Scale)"].hide=True
  285. elif nc.evaluate_input("Map To") == "SCALE":
  286. self.inputs["Rotation Order"].hide=True
  287. self.inputs["Mix Mode (Translation)"].hide=True
  288. self.inputs["Mix Mode (Rotation)"].hide=True
  289. self.inputs["Mix Mode (Scale)"].hide=False
  290. class LinkArmatureNode(Node, LinkNode):
  291. """A node representing Blender's Armature Constraint"""
  292. bl_idname = "LinkArmature"
  293. bl_label = "Armature (Constraint)"
  294. bl_icon = "CON_ARMATURE"
  295. initialized : bpy.props.BoolProperty(default = False)
  296. mantis_node_class_name=bl_idname
  297. def init(self, context):
  298. self.init_sockets(LinkArmatureSockets)
  299. self.use_custom_color = True
  300. self.color = inheritColor
  301. self.initialized = True
  302. def draw_buttons(self, context, layout):
  303. # return
  304. layout.operator( 'mantis.link_armature_node_add_target' )
  305. if (len(self.inputs) > 6):
  306. layout.operator( 'mantis.link_armature_node_remove_target' )
  307. else:
  308. layout.label(text="")
  309. class LinkSplineIKNode(Node, LinkNode):
  310. """"A node representing Spline IK"""
  311. bl_idname = "LinkSplineIK"
  312. bl_label = "Spline IK"
  313. bl_icon = "CON_SPLINEIK"
  314. initialized : bpy.props.BoolProperty(default = False)
  315. mantis_node_class_name=bl_idname
  316. def init(self, context):
  317. self.init_sockets(LinkSplineIKSockets)
  318. self.use_custom_color = True
  319. self.color = ikColor
  320. self.initialized = True
  321. # DRIVERS!!
  322. class LinkDrivenParameterNode(Node, LinkNode):
  323. """Represents a driven parameter in the downstream xForm node."""
  324. bl_idname = "LinkDrivenParameter"
  325. bl_label = "Driven Parameter"
  326. bl_icon = "CONSTRAINT_BONE"
  327. initialized : bpy.props.BoolProperty(default = False)
  328. mantis_node_class_name=bl_idname
  329. def init(self, context):
  330. self.init_sockets(LinkDrivenParameterSockets)
  331. self.use_custom_color = True
  332. self.color = linkColor
  333. self.initialized = True
  334. # Set up the class property that ties the UI classes to the Mantis classes.
  335. for cls in TellClasses():
  336. cls.set_mantis_class()