link_definitions.py 14 KB

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