link_nodes_ui.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. import bpy
  2. from bpy.types import NodeTree, Node, NodeSocket
  3. from .base_definitions import LinkNode, GraphError
  4. from .utilities.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. LinkShrinkWrapNode,
  31. LinkGeometryAttribute,
  32. LinkTransformationNode,
  33. ]
  34. from mathutils import Color # these colors were sampled from Blender's UI
  35. # TODO: maybe read the relevant colors from the Theme
  36. linkTransformColor = Color((0.028034, 0.093164, 0.070379)).from_scene_linear_to_srgb()
  37. inheritColor = Color((0.083213, 0.131242, 0.116497)).from_scene_linear_to_srgb()
  38. trackingColor = Color((0.033114, 0.049013, 0.131248)).from_scene_linear_to_srgb()
  39. ikColor = Color((0.131117, 0.131248, 0.006971)).from_scene_linear_to_srgb()
  40. driverColor = Color((0.043782, 0.014745, 0.131248,)).from_scene_linear_to_srgb()
  41. class LinkInheritNode(Node, LinkNode):
  42. '''A node representing inheritance'''
  43. # cuss, messed this up
  44. bl_idname = 'linkInherit' # l should be L
  45. # need to fix this
  46. bl_label = "Inherit"
  47. bl_icon = 'CONSTRAINT_BONE'
  48. mantis_node_class_name="LinkInherit"
  49. socket_templates = LinkInheritSockets
  50. category_color=inheritColor
  51. def display_update(self, parsed_tree, context):
  52. node_tree = context.space_data.path[0].node_tree
  53. mantis_node = parsed_tree.get(get_signature_from_edited_tree(self, context))
  54. if mantis_node:
  55. bone_prev, bone_next = False, False
  56. if (inp := mantis_node.inputs["Parent"]).is_connected:
  57. if from_node := inp.links[0].from_node:
  58. if from_node.__class__.__name__ in ["xFormBone"]:
  59. bone_prev=True
  60. bone_next=True
  61. try:
  62. xForm = mantis_node.GetxForm()
  63. if xForm.__class__.__name__ not in "xFormBone":
  64. bone_next=False
  65. except GraphError:
  66. bone_next=False
  67. # print(bone_prev, bone_next )
  68. if bone_next and bone_prev:
  69. self.inputs["Inherit Rotation"].hide = False
  70. self.inputs["Inherit Scale"].hide = False
  71. self.inputs["Connected"].hide = False
  72. else:
  73. self.inputs["Inherit Rotation"].hide = True or self.inputs["Inherit Rotation"].is_connected
  74. self.inputs["Inherit Scale"].hide = True or self.inputs["Inherit Scale"].is_connected
  75. self.inputs["Connected"].hide = True or self.inputs["Connected"].is_connected
  76. # the node_groups on the way here ought to be active if there
  77. # is no funny business going on.
  78. # DO: make another node for ITASC IK, eh?
  79. class LinkInverseKinematics(Node, LinkNode):
  80. '''A node representing inverse kinematics'''
  81. bl_idname = 'LinkInverseKinematics'
  82. bl_label = "Inverse Kinematics"
  83. bl_icon = 'CON_KINEMATIC'
  84. mantis_node_class_name=bl_idname
  85. category_color=linkTransformColor
  86. socket_templates = LinkInverseKinematicsSockets
  87. class LinkCopyLocationNode(Node, LinkNode):
  88. '''A node representing Copy Location'''
  89. bl_idname = 'LinkCopyLocation'
  90. bl_label = "Copy Location"
  91. bl_icon = 'CON_LOCLIKE'
  92. mantis_node_class_name=bl_idname
  93. category_color=linkTransformColor
  94. socket_templates = LinkCopyLocationSockets
  95. class LinkCopyRotationNode(Node, LinkNode):
  96. '''A node representing Copy Rotation'''
  97. bl_idname = 'LinkCopyRotation'
  98. bl_label = "Copy Rotation"
  99. bl_icon = 'CON_ROTLIKE'
  100. mantis_node_class_name=bl_idname
  101. category_color=linkTransformColor
  102. socket_templates = LinkCopyRotationSockets
  103. class LinkCopyScaleNode(Node, LinkNode):
  104. '''A node representing Copy Scale'''
  105. bl_idname = 'LinkCopyScale'
  106. bl_label = "Copy Scale"
  107. bl_icon = 'CON_SIZELIKE'
  108. mantis_node_class_name=bl_idname
  109. category_color=linkTransformColor
  110. socket_templates = LinkCopyScaleSockets
  111. class LinkInheritConstraintNode(Node, LinkNode):
  112. '''A node representing a parent constraint'''
  113. bl_idname = 'LinkInheritConstraint'
  114. bl_label = "Inherit (constraint)"
  115. bl_icon = 'CON_CHILDOF'
  116. mantis_node_class_name=bl_idname
  117. category_color=inheritColor
  118. socket_templates = LinkInheritConstraintSockets
  119. class LinkCopyTransformNode(Node, LinkNode):
  120. '''A node representing Copy Transform'''
  121. bl_idname = 'LinkCopyTransforms'
  122. bl_label = "Copy Transform"
  123. bl_icon = 'CON_TRANSLIKE'
  124. mantis_node_class_name=bl_idname
  125. category_color=linkTransformColor
  126. socket_templates = LinkCopyTransformsSockets
  127. class LinkStretchToNode(Node, LinkNode):
  128. '''A node representing Stretch-To'''
  129. bl_idname = 'LinkStretchTo'
  130. bl_label = "Stretch To"
  131. bl_icon = 'CON_STRETCHTO'
  132. mantis_node_class_name=bl_idname
  133. category_color=trackingColor
  134. socket_templates = LinkStretchToSockets
  135. class LinkDampedTrackNode(Node, LinkNode):
  136. '''A node representing Stretch-To'''
  137. bl_idname = 'LinkDampedTrack'
  138. bl_label = "Damped Track"
  139. bl_icon = 'CON_TRACKTO'
  140. mantis_node_class_name=bl_idname
  141. category_color=trackingColor
  142. socket_templates = LinkDampedTrackSockets
  143. class LinkLockedTrackNode(Node, LinkNode):
  144. '''A node representing Stretch-To'''
  145. bl_idname = 'LinkLockedTrack'
  146. bl_label = "Locked Track"
  147. bl_icon = 'CON_LOCKTRACK'
  148. mantis_node_class_name=bl_idname
  149. category_color=trackingColor
  150. socket_templates = LinkLockedTrackSockets
  151. class LinkTrackToNode(Node, LinkNode):
  152. '''A node representing Stretch-To'''
  153. bl_idname = 'LinkTrackTo'
  154. bl_label = "Track To"
  155. bl_icon = 'CON_TRACKTO'
  156. mantis_node_class_name=bl_idname
  157. category_color=trackingColor
  158. socket_templates = LinkTrackToSockets
  159. class LinkLimitLocationNode(Node, LinkNode):
  160. '''A node representing Limit Location'''
  161. bl_idname = 'LinkLimitLocation'
  162. bl_label = "Limit Location"
  163. bl_icon = 'CON_LOCLIMIT'
  164. mantis_node_class_name=bl_idname
  165. category_color=linkTransformColor
  166. socket_templates = LinkLimitLocationSockets
  167. class LinkLimitScaleNode(Node, LinkNode):
  168. '''A node representing Limit Scale'''
  169. bl_idname = 'LinkLimitScale'
  170. bl_label = "Limit Scale"
  171. bl_icon = 'CON_SIZELIMIT'
  172. mantis_node_class_name=bl_idname
  173. category_color=linkTransformColor
  174. socket_templates = LinkLimitScaleSockets
  175. class LinkLimitRotationNode(Node, LinkNode):
  176. '''A node representing Limit Rotation'''
  177. bl_idname = 'LinkLimitRotation'
  178. bl_label = "Limit Rotation"
  179. bl_icon = 'CON_ROTLIMIT'
  180. mantis_node_class_name=bl_idname
  181. category_color=linkTransformColor
  182. socket_templates = LinkLimitRotationSockets
  183. class LinkLimitDistanceNode(Node, LinkNode):
  184. '''A node representing Limit Distance'''
  185. bl_idname = 'LinkLimitDistance'
  186. bl_label = "Limit Distance"
  187. bl_icon = 'CON_DISTLIMIT'
  188. mantis_node_class_name=bl_idname
  189. category_color=linkTransformColor
  190. socket_templates = LinkLimitDistanceSockets
  191. class LinkTransformationNode(Node, LinkNode):
  192. '''A node representing Transformation (Constraint)'''
  193. bl_idname = 'LinkTransformation'
  194. bl_label = "Transformation"
  195. bl_icon = 'CON_TRANSFORM'
  196. mantis_node_class_name=bl_idname
  197. category_color=linkTransformColor
  198. socket_templates = LinkTransformationSockets
  199. def display_update(self, parsed_tree, context):
  200. node_tree = context.space_data.path[0].node_tree
  201. mantis_node = parsed_tree.get(get_signature_from_edited_tree(self, context))
  202. if mantis_node:
  203. if mantis_node.evaluate_input("Map From") == "ROTATION":
  204. self.inputs["Rotation Mode"].hide=False
  205. else:
  206. self.inputs["Rotation Mode"].hide=True
  207. if mantis_node.evaluate_input("Map To") == "TRANSLATION":
  208. self.inputs["Rotation Order"].hide=True
  209. self.inputs["Mix Mode (Translation)"].hide=False
  210. self.inputs["Mix Mode (Rotation)"].hide=True
  211. self.inputs["Mix Mode (Scale)"].hide=True
  212. elif mantis_node.evaluate_input("Map To") == "ROTATION":
  213. self.inputs["Rotation Order"].hide=False
  214. self.inputs["Mix Mode (Translation)"].hide=True
  215. self.inputs["Mix Mode (Rotation)"].hide=False
  216. self.inputs["Mix Mode (Scale)"].hide=True
  217. elif mantis_node.evaluate_input("Map To") == "SCALE":
  218. self.inputs["Rotation Order"].hide=True
  219. self.inputs["Mix Mode (Translation)"].hide=True
  220. self.inputs["Mix Mode (Rotation)"].hide=True
  221. self.inputs["Mix Mode (Scale)"].hide=False
  222. class LinkArmatureNode(Node, LinkNode):
  223. """A node representing Blender's Armature Constraint"""
  224. bl_idname = "LinkArmature"
  225. bl_label = "Armature (Constraint)"
  226. bl_icon = "CON_ARMATURE"
  227. mantis_node_class_name=bl_idname
  228. category_color=inheritColor
  229. socket_templates = LinkArmatureSockets
  230. class LinkSplineIKNode(Node, LinkNode):
  231. """"A node representing Spline IK"""
  232. bl_idname = "LinkSplineIK"
  233. bl_label = "Spline IK"
  234. bl_icon = "CON_SPLINEIK"
  235. mantis_node_class_name=bl_idname
  236. category_color=ikColor
  237. socket_templates = LinkSplineIKSockets
  238. class LinkFloorNode(Node, LinkNode):
  239. """A node representing Blender's Floor Constraint"""
  240. bl_idname = "LinkFloor"
  241. bl_label = "Floor"
  242. bl_icon = "CON_FLOOR"
  243. mantis_node_class_name=bl_idname
  244. category_color=linkTransformColor
  245. socket_templates = LinkFloorSockets
  246. class LinkShrinkWrapNode(Node, LinkNode):
  247. """A node representing Blender's Shrinkwrap Constraint"""
  248. bl_idname = "LinkShrinkWrap"
  249. bl_label = "Shrinkwrap"
  250. bl_icon = "CON_SHRINKWRAP"
  251. mantis_node_class_name=bl_idname
  252. category_color=trackingColor
  253. socket_templates = LinkShrinkWrapSockets
  254. def display_update(self, parsed_tree, context):
  255. # vast majority of the time user doesn't link this.
  256. shrink_type = self.inputs['Mode'].default_value
  257. if self.inputs['Mode'].is_linked:# 1% or less of cases
  258. node_tree = context.space_data.path[0].node_tree
  259. mantis_node = parsed_tree.get(get_signature_from_edited_tree(self, context))
  260. shrink_is_project = False
  261. if mantis_node:
  262. shrink_type = mantis_node.evaluate_input("Mode")
  263. if shrink_type != "PROJECT":
  264. self.inputs['Project Axis'].hide=True
  265. self.inputs['Space'].hide=True
  266. self.inputs['Project Distance'].hide=True
  267. self.inputs['Project Opposite'].hide=True
  268. self.inputs['Face Cull'].hide=True
  269. self.inputs['Invert Cull'].hide=True
  270. else:
  271. for inp in self.inputs:
  272. inp.hide=False
  273. if shrink_type == 'NEAREST_VERTEX':
  274. self.inputs['Snap Mode'].hide=True
  275. self.inputs['Align to Normal'].hide=True
  276. self.inputs['Align Normal Axis'].hide=True
  277. else:
  278. self.inputs['Snap Mode'].hide=False
  279. self.inputs['Align to Normal'].hide=False
  280. self.inputs['Align Normal Axis'].hide=False
  281. # TODO: this stuff should be handled by input tags
  282. # once I get that working.
  283. class LinkGeometryAttribute(Node, LinkNode):
  284. """A node representing Blender's Geometry Attribute Constraint"""
  285. bl_idname = "LinkGeometryAttribute"
  286. bl_label = "Geometry Attribute"
  287. if bpy.app.version >= (5,0,0):
  288. bl_icon = "CON_GEOMETRYATTRIBUTE"
  289. else:
  290. bl_icon = "ERROR"
  291. mantis_node_class_name=bl_idname
  292. category_color=linkTransformColor
  293. socket_templates = LinkGeometryAttributeSockets
  294. def draw_label(self):
  295. if bpy.app.version < (5,0,0):
  296. return "ERROR: ONLY SUPPORTED IN Blender 5.0 OR NEWER"
  297. elif self.label:
  298. return self.label
  299. return self.bl_label
  300. def update(self):
  301. if bpy.app.version < (5,0,0):
  302. self.color = Color((1.0, 0.15, 0.15,)).from_scene_linear_to_srgb()
  303. elif self.color != linkTransformColor:
  304. self.color = linkTransformColor
  305. def display_update(self, parsed_tree, context):
  306. if bpy.app.version < (5,0,0):
  307. return
  308. data_type = self.inputs['Data Type'].default_value
  309. if self.inputs['Data Type'].is_linked:
  310. node_tree = context.space_data.path[0].node_tree
  311. mantis_node = parsed_tree.get(get_signature_from_edited_tree(self, context))
  312. if mantis_node: data_type = mantis_node.evaluate_input("Data Type")
  313. not_matrix_mode = (data_type != 'FLOAT4X4')
  314. self.inputs['Enabled Location'].hide=not_matrix_mode
  315. self.inputs['Enabled Rotation'].hide=not_matrix_mode
  316. self.inputs['Enabled Scale'].hide=not_matrix_mode
  317. # DRIVERS!!
  318. class LinkDrivenParameterNode(Node, LinkNode):
  319. """Represents a driven parameter in the downstream xForm node."""
  320. bl_idname = "LinkDrivenParameter"
  321. bl_label = "Driven Parameter"
  322. bl_icon = "CONSTRAINT_BONE"
  323. mantis_node_class_name=bl_idname
  324. category_color=linkTransformColor
  325. socket_templates = LinkDrivenParameterSockets