link_definitions.py 15 KB

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