link_definitions.py 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655
  1. import bpy
  2. from bpy.types import NodeTree, Node, NodeSocket
  3. from .base_definitions import MantisNode, 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. def default_traverse(self, socket):
  31. if (socket == self.outputs["Output Relationship"]):
  32. return self.inputs["Input Relationship"]
  33. if (socket == self.inputs["Input Relationship"]):
  34. return self.outputs["Output Relationship"]
  35. return None
  36. class LinkInheritNode(Node, LinkNode):
  37. '''A node representing inheritance'''
  38. # cuss, messed this up
  39. bl_idname = 'linkInherit' # l should be L
  40. # need to fix this
  41. bl_label = "Inherit"
  42. bl_icon = 'CONSTRAINT_BONE'
  43. initialized : bpy.props.BoolProperty(default = False)
  44. useTarget : bpy.props.BoolProperty(default=False)
  45. # bone_prev : bpy.props.BoolProperty(default=False)
  46. # bone_next : bpy.props.BoolProperty(default=False)
  47. def init(self, context):
  48. r = self.inputs.new('BooleanSocket', "Inherit Rotation")
  49. s = self.inputs.new('EnumInheritScale', "Inherit Scale")
  50. c = self.inputs.new('BooleanSocket', "Connected")
  51. i = self.outputs.new('RelationshipSocket', "Inheritance")
  52. p = self.inputs.new('xFormSocket', "Parent")
  53. # set default values...
  54. self.initialized = True
  55. def traverse(self, socket):
  56. if (socket == self.outputs["Inheritance"]):
  57. return self.inputs["Parent"]
  58. if (socket == self.inputs["Parent"]):
  59. return self.outputs["Inheritance"]
  60. return None
  61. def display_update(self, parsed_tree, context):
  62. node_tree = context.space_data.path[0].node_tree
  63. nc = parsed_tree.get(get_signature_from_edited_tree(self, context))
  64. if nc:
  65. bone_prev, bone_next = False, False
  66. if (inp := nc.inputs["Parent"]).is_connected:
  67. if from_node := inp.links[0].from_node:
  68. if from_node.__class__.__name__ in ["xFormBone"]:
  69. bone_prev=True
  70. bone_next=True
  71. try:
  72. xForm = nc.GetxForm()
  73. if xForm.__class__.__name__ not in "xFormBone":
  74. bone_next=False
  75. except GraphError:
  76. bone_next=False
  77. # print(bone_prev, bone_next )
  78. if bone_next and bone_prev:
  79. self.inputs["Inherit Rotation"].hide = False
  80. self.inputs["Inherit Scale"].hide = False
  81. self.inputs["Connected"].hide = False
  82. else:
  83. self.inputs["Inherit Rotation"].hide = True
  84. self.inputs["Inherit Scale"].hide = True
  85. self.inputs["Connected"].hide = True
  86. # the node_groups on the way here ought to be active if there
  87. # is no funny business going on.
  88. # DO: make another node for ITASC IK, eh?
  89. class LinkInverseKinematics(Node, LinkNode):
  90. '''A node representing inverse kinematics'''
  91. bl_idname = 'LinkInverseKinematics'
  92. bl_label = "Inverse Kinematics"
  93. bl_icon = 'CON_KINEMATIC'
  94. initialized : bpy.props.BoolProperty(default = False)
  95. useTarget : bpy.props.BoolProperty(default=True)
  96. def init(self, context):
  97. self.inputs.new('RelationshipSocket', "Input Relationship")
  98. self.inputs.new ('xFormSocket', "Target")
  99. self.inputs.new ('xFormSocket', "Pole Target")
  100. self.inputs.new ('IKChainLengthSocket', "Chain Length")
  101. self.inputs.new ('BooleanSocket', "Use Tail")
  102. self.inputs.new ('BooleanSocket', "Stretch")
  103. self.inputs.new ('FloatFactorSocket', "Position")
  104. self.inputs.new ('FloatFactorSocket', "Rotation")
  105. self.inputs.new ('FloatFactorSocket', "Influence")
  106. self.inputs.new ('EnableSocket', "Enable")
  107. #Well, it turns out that this has to be a constraint like
  108. # everything else, because of course, there can be more than one.
  109. #self.outputs.new('RelationshipSocket', "Inheritance")
  110. self.outputs.new('RelationshipSocket', "Output Relationship")
  111. self.initialized = True
  112. class LinkSplineIK(Node, LinkNode):
  113. '''A node representing Spline IK'''
  114. bl_idname = 'LinkSplineIK'
  115. bl_label = "LinkSplineIK"
  116. bl_icon = 'CON_SPLINEIK'
  117. useTarget : bpy.props.BoolProperty(default=True)
  118. def init(self, context):
  119. self.inputs.new('xFormSocket', "Parent")
  120. self.inputs.new ('xFormSocket', "Target")
  121. self.inputs.new ('xFormSocket', "Pole Target")
  122. self.inputs.new ('BooleanSocket', "Use Tail")
  123. self.inputs.new ('BooleanSocket', "Stretch")
  124. self.inputs.new ('FloatFactorSocket', "Position")
  125. self.inputs.new ('FloatFactorSocket', "Rotation")
  126. self.inputs.new ('FloatFactorSocket', "Influence")
  127. self.inputs.new ('EnableSocket', "Enable")
  128. self.outputs.new('RelationshipSocket', "Inheritance")
  129. def traverse(self, socket):
  130. if (socket == self.outputs["Inheritance"]):
  131. return self.inputs["Parent"]
  132. if (socket == self.inputs["Parent"]):
  133. return self.outputs["Inheritance"]
  134. return None
  135. class LinkCopyLocationNode(Node, LinkNode):
  136. '''A node representing Copy Location'''
  137. bl_idname = 'LinkCopyLocation'
  138. bl_label = "Copy Location"
  139. bl_icon = 'CON_LOCLIKE'
  140. useTarget : bpy.props.BoolProperty(default=True)
  141. def init(self, context):
  142. self.inputs.new ('RelationshipSocket', "Input Relationship")
  143. self.inputs.new ('FloatFactorSocket', "Head/Tail")
  144. self.inputs.new ('BooleanSocket', "UseBBone")
  145. self.inputs.new ('BooleanThreeTupleSocket', "Axes")
  146. self.inputs.new ('BooleanThreeTupleSocket', "Invert")
  147. self.inputs.new ('TransformSpaceSocket', "Target Space")
  148. self.inputs.new ('TransformSpaceSocket', "Owner Space")
  149. self.inputs.new ('FloatFactorSocket', "Influence")
  150. self.inputs.new ('xFormSocket', "Target")
  151. self.inputs.new ('EnableSocket', "Enable")
  152. #
  153. self.outputs.new('RelationshipSocket', "Output Relationship")
  154. # def display_update(self, parsed_tree, context):
  155. # node_tree = context.space_data.path[0].node_tree
  156. # nc = parsed_tree.get(get_signature_from_edited_tree(self, context))
  157. # if nc:
  158. # bone_prev, bone_next = False, False
  159. # if (inp := nc.inputs["Input Relationship"]).is_connected:
  160. # if from_node := inp.links[0].from_node:
  161. # if from_node.__class__.__name__ in ["xFormBone"]:
  162. # bone_prev=True
  163. # bone_next=True
  164. # try:
  165. # xForm = nc.GetxForm()
  166. # if xForm.__class__.__name__ not in "xFormBone":
  167. # bone_next=False
  168. # except GraphError:
  169. # bone_next=False
  170. # if bone_next and bone_prev:
  171. # # this is where we will set whether you can pick
  172. # # the other spaces or not.
  173. class LinkCopyRotationNode(Node, LinkNode):
  174. '''A node representing Copy Rotation'''
  175. bl_idname = 'LinkCopyRotation'
  176. bl_label = "Copy Rotation"
  177. bl_icon = 'CON_ROTLIKE'
  178. useTarget : bpy.props.BoolProperty(default=True)
  179. def init(self, context):
  180. self.inputs.new ('RelationshipSocket', "Input Relationship")
  181. self.inputs.new ('RotationOrderSocket', "RotationOrder")
  182. self.inputs.new ('EnumRotationMix', "Rotation Mix")
  183. self.inputs.new ('BooleanThreeTupleSocket', "Axes")
  184. self.inputs.new ('BooleanThreeTupleSocket', "Invert")
  185. self.inputs.new ('TransformSpaceSocket', "Target Space")
  186. self.inputs.new ('TransformSpaceSocket', "Owner Space")
  187. self.inputs.new ('FloatFactorSocket', "Influence")
  188. self.inputs.new ('xFormSocket', "Target")
  189. self.inputs.new ('EnableSocket', "Enable")
  190. #
  191. self.outputs.new('RelationshipSocket', "Output Relationship")
  192. class LinkCopyScaleNode(Node, LinkNode):
  193. '''A node representing Copy Scale'''
  194. bl_idname = 'LinkCopyScale'
  195. bl_label = "Copy Scale"
  196. bl_icon = 'CON_SIZELIKE'
  197. useTarget : bpy.props.BoolProperty(default=True)
  198. def init(self, context):
  199. self.inputs.new ('RelationshipSocket', "Input Relationship")
  200. self.inputs.new ('BooleanSocket', "Offset")
  201. self.inputs.new ('BooleanSocket', "Average")
  202. self.inputs.new ('BooleanThreeTupleSocket', "Axes")
  203. #self.inputs.new ('BooleanThreeTupleSocket', "Invert")
  204. # dingus, this one doesn't have inverts
  205. self.inputs.new ('TransformSpaceSocket', "Target Space")
  206. self.inputs.new ('TransformSpaceSocket', "Owner Space")
  207. self.inputs.new ('FloatFactorSocket', "Influence")
  208. self.inputs.new ('xFormSocket', "Target")
  209. self.inputs.new ('EnableSocket', "Enable")
  210. #
  211. self.outputs.new('RelationshipSocket', "Output Relationship")
  212. class LinkInheritConstraintNode(Node, LinkNode):
  213. # === Basics ===
  214. # Description string
  215. '''A node representing a parent constraint'''
  216. bl_idname = 'LinkInheritConstraint'
  217. bl_label = "Inherit (constraint)"
  218. bl_icon = 'CON_CHILDOF'
  219. useTarget : bpy.props.BoolProperty(default=True)
  220. # === Optional Functions ===
  221. def init(self, context):
  222. self.inputs.new ('RelationshipSocket', "Input Relationship")
  223. self.inputs.new ('BooleanThreeTupleSocket', "Location")
  224. self.inputs.new ('BooleanThreeTupleSocket', "Rotation")
  225. self.inputs.new ('BooleanThreeTupleSocket', "Scale")
  226. self.inputs.new ('FloatFactorSocket', "Influence")
  227. self.inputs.new ('xFormSocket', "Target")
  228. self.inputs.new ('EnableSocket', "Enable")
  229. #
  230. self.outputs.new('RelationshipSocket', "Output Relationship")
  231. class LinkCopyTransformNode(Node, LinkNode):
  232. # === Basics ===
  233. # Description string
  234. '''A node representing Copy Transform'''
  235. bl_idname = 'LinkCopyTransforms'
  236. bl_label = "Copy Transform"
  237. bl_icon = 'CON_TRANSLIKE'
  238. useTarget : bpy.props.BoolProperty(default=True)
  239. # === Optional Functions ===
  240. def init(self, context):
  241. self.inputs.new ('RelationshipSocket', "Input Relationship")
  242. self.inputs.new ('FloatFactorSocket', "Head/Tail")
  243. self.inputs.new ('BooleanSocket', "UseBBone")
  244. self.inputs.new ('EnumRotationMixCopyTransforms', "Mix")
  245. self.inputs.new ('TransformSpaceSocket', "Target Space")
  246. self.inputs.new ('TransformSpaceSocket', "Owner Space")
  247. self.inputs.new ('FloatFactorSocket', "Influence")
  248. self.inputs.new ('xFormSocket', "Target")
  249. self.inputs.new ('EnableSocket', "Enable")
  250. #
  251. self.outputs.new('RelationshipSocket', "Output Relationship")
  252. class LinkStretchToNode(Node, LinkNode):
  253. '''A node representing Stretch-To'''
  254. bl_idname = 'LinkStretchTo'
  255. bl_label = "Stretch To"
  256. bl_icon = 'CON_STRETCHTO'
  257. useTarget : bpy.props.BoolProperty(default=True)
  258. initialized : bpy.props.BoolProperty(default = False)
  259. def init(self, context):
  260. self.inputs.new ('RelationshipSocket', "Input Relationship")
  261. self.inputs.new ('FloatFactorSocket', "Head/Tail")
  262. self.inputs.new ('BooleanSocket', "UseBBone")
  263. self.inputs.new ('FloatSocket', "Original Length")
  264. self.inputs.new ('FloatSocket', "Volume Variation")
  265. self.inputs.new ('BoolUpdateParentNode', "Use Volume Min")
  266. self.inputs.new ('FloatSocket', "Volume Min")
  267. self.inputs.new ('BoolUpdateParentNode', "Use Volume Max")
  268. self.inputs.new ('FloatSocket', "Volume Max")
  269. self.inputs.new ('FloatFactorSocket', "Smooth")
  270. self.inputs.new ('EnumMaintainVolumeStretchToSocket', "Maintain Volume")
  271. self.inputs.new ('EnumRotationStretchTo', "Rotation")
  272. self.inputs.new ('FloatFactorSocket', "Influence")
  273. self.inputs.new ('xFormSocket', "Target")
  274. self.inputs.new ('EnableSocket', "Enable")
  275. #
  276. self.outputs.new('RelationshipSocket', "Output Relationship")
  277. self.initialized = True
  278. class LinkDampedTrackNode(Node, LinkNode):
  279. '''A node representing Stretch-To'''
  280. bl_idname = 'LinkDampedTrack'
  281. bl_label = "Damped Track"
  282. bl_icon = 'CON_TRACKTO'
  283. useTarget : bpy.props.BoolProperty(default=True)
  284. initialized : bpy.props.BoolProperty(default = False)
  285. def init(self, context):
  286. self.inputs.new ('RelationshipSocket', "Input Relationship")
  287. self.inputs.new ('FloatFactorSocket', "Head/Tail")
  288. self.inputs.new ('BooleanSocket', "UseBBone")
  289. self.inputs.new ('EnumTrackAxis', "Track Axis")
  290. self.inputs.new ('FloatFactorSocket', "Influence")
  291. self.inputs.new ('xFormSocket', "Target")
  292. self.inputs.new ('EnableSocket', "Enable")
  293. #
  294. self.outputs.new('RelationshipSocket', "Output Relationship")
  295. self.initialized = True
  296. class LinkLockedTrackNode(Node, LinkNode):
  297. '''A node representing Stretch-To'''
  298. bl_idname = 'LinkLockedTrack'
  299. bl_label = "Locked Track"
  300. bl_icon = 'CON_LOCKTRACK'
  301. useTarget : bpy.props.BoolProperty(default=True)
  302. initialized : bpy.props.BoolProperty(default = False)
  303. def init(self, context):
  304. self.inputs.new ('RelationshipSocket', "Input Relationship")
  305. self.inputs.new ('FloatFactorSocket', "Head/Tail")
  306. self.inputs.new ('BooleanSocket', "UseBBone")
  307. self.inputs.new ('EnumTrackAxis', "Track Axis")
  308. self.inputs.new ('EnumLockAxis', "Lock Axis")
  309. self.inputs.new ('FloatFactorSocket', "Influence")
  310. self.inputs.new ('xFormSocket', "Target")
  311. self.inputs.new ('EnableSocket', "Enable")
  312. #
  313. self.outputs.new('RelationshipSocket', "Output Relationship")
  314. self.initialized = True
  315. class LinkTrackToNode(Node, LinkNode):
  316. '''A node representing Stretch-To'''
  317. bl_idname = 'LinkTrackTo'
  318. bl_label = "Track To"
  319. bl_icon = 'CON_TRACKTO'
  320. useTarget : bpy.props.BoolProperty(default=True)
  321. initialized : bpy.props.BoolProperty(default = False)
  322. def init(self, context):
  323. self.inputs.new ('RelationshipSocket', "Input Relationship")
  324. self.inputs.new ('FloatFactorSocket', "Head/Tail")
  325. self.inputs.new ('BooleanSocket', "UseBBone")
  326. self.inputs.new ('EnumTrackAxis', "Track Axis")
  327. self.inputs.new ('EnumUpAxis', "Up Axis")
  328. self.inputs.new ('BooleanSocket', "Use Target Z")
  329. self.inputs.new ('TransformSpaceSocket', "Target Space")
  330. self.inputs.new ('TransformSpaceSocket', "Owner Space")
  331. self.inputs.new ('FloatFactorSocket', "Influence")
  332. self.inputs.new ('xFormSocket', "Target")
  333. self.inputs.new ('EnableSocket', "Enable")
  334. #
  335. self.outputs.new('RelationshipSocket', "Output Relationship")
  336. self.initialized = True
  337. class LinkLimitLocationNode(Node, LinkNode):
  338. '''A node representing Limit Location'''
  339. bl_idname = 'LinkLimitLocation'
  340. bl_label = "Limit Location"
  341. bl_icon = 'CON_LOCLIMIT'
  342. useTarget : bpy.props.BoolProperty(default=False)
  343. initialized : bpy.props.BoolProperty(default = False)
  344. def init(self, context):
  345. self.inputs.new ('RelationshipSocket', "Input Relationship")
  346. self.inputs.new ('BoolUpdateParentNode', "Use Max X")
  347. self.inputs.new ('FloatSocket', "Max X")
  348. self.inputs.new ('BoolUpdateParentNode', "Use Min X")
  349. self.inputs.new ('FloatSocket', "Min X")
  350. self.inputs.new ('BoolUpdateParentNode', "Use Max Y")
  351. self.inputs.new ('FloatSocket', "Max Y")
  352. self.inputs.new ('BoolUpdateParentNode', "Use Min Y")
  353. self.inputs.new ('FloatSocket', "Min Y")
  354. self.inputs.new ('BoolUpdateParentNode', "Use Max Z")
  355. self.inputs.new ('FloatSocket', "Max Z")
  356. self.inputs.new ('BoolUpdateParentNode', "Use Min Z")
  357. self.inputs.new ('FloatSocket', "Min Z")
  358. self.inputs.new ('BooleanSocket', "Affect Transform")
  359. self.inputs.new ('TransformSpaceSocket', "Owner Space")
  360. self.inputs.new ('FloatFactorSocket', "Influence")
  361. self.inputs.new ('EnableSocket', "Enable")
  362. #
  363. self.outputs.new('RelationshipSocket', "Output Relationship")
  364. self.initialized = True
  365. class LinkLimitScaleNode(Node, LinkNode):
  366. '''A node representing Limit Scale'''
  367. bl_idname = 'LinkLimitScale'
  368. bl_label = "Limit Scale"
  369. bl_icon = 'CON_SIZELIMIT'
  370. useTarget : bpy.props.BoolProperty(default=False)
  371. initialized : bpy.props.BoolProperty(default = False)
  372. def init(self, context):
  373. self.inputs.new ('RelationshipSocket', "Input Relationship")
  374. self.inputs.new ('BoolUpdateParentNode', "Use Max X")
  375. self.inputs.new ('FloatSocket', "Max X")
  376. self.inputs.new ('BoolUpdateParentNode', "Use Min X")
  377. self.inputs.new ('FloatSocket', "Min X")
  378. self.inputs.new ('BoolUpdateParentNode', "Use Max Y")
  379. self.inputs.new ('FloatSocket', "Max Y")
  380. self.inputs.new ('BoolUpdateParentNode', "Use Min Y")
  381. self.inputs.new ('FloatSocket', "Min Y")
  382. self.inputs.new ('BoolUpdateParentNode', "Use Max Z")
  383. self.inputs.new ('FloatSocket', "Max Z")
  384. self.inputs.new ('BoolUpdateParentNode', "Use Min Z")
  385. self.inputs.new ('FloatSocket', "Min Z")
  386. self.inputs.new ('BooleanSocket', "Affect Transform")
  387. self.inputs.new ('TransformSpaceSocket', "Owner Space")
  388. self.inputs.new ('FloatFactorSocket', "Influence")
  389. self.inputs.new ('EnableSocket', "Enable")
  390. #
  391. self.outputs.new('RelationshipSocket', "Output Relationship")
  392. self.initialized = True
  393. class LinkLimitRotationNode(Node, LinkNode):
  394. # === Basics ===
  395. # Description string
  396. '''A node representing Limit Rotation'''
  397. bl_idname = 'LinkLimitRotation'
  398. bl_label = "Limit Rotation"
  399. bl_icon = 'CON_ROTLIMIT'
  400. useTarget : bpy.props.BoolProperty(default=False)
  401. initialized : bpy.props.BoolProperty(default = False)
  402. # === Optional Functions ===
  403. def init(self, context):
  404. self.inputs.new ('RelationshipSocket', "Input Relationship")
  405. self.inputs.new ('BoolUpdateParentNode', "Use X")
  406. self.inputs.new ('FloatAngleSocket', "Min X")
  407. self.inputs.new ('FloatAngleSocket', "Max X")
  408. self.inputs.new ('BoolUpdateParentNode', "Use Y")
  409. self.inputs.new ('FloatAngleSocket', "Min Y")
  410. self.inputs.new ('FloatAngleSocket', "Max Y")
  411. self.inputs.new ('BoolUpdateParentNode', "Use Z")
  412. self.inputs.new ('FloatAngleSocket', "Min Z")
  413. self.inputs.new ('FloatAngleSocket', "Max Z")
  414. self.inputs.new ('BooleanSocket', "Affect Transform")
  415. self.inputs.new ('TransformSpaceSocket', "Owner Space")
  416. self.inputs.new ('FloatFactorSocket', "Influence")
  417. self.inputs.new ('EnableSocket', "Enable")
  418. #
  419. self.outputs.new('RelationshipSocket', "Output Relationship")
  420. self.initialized = True
  421. class LinkLimitDistanceNode(Node, LinkNode):
  422. '''A node representing Limit Distance'''
  423. bl_idname = 'LinkLimitDistance'
  424. bl_label = "Limit Distance"
  425. bl_icon = 'CON_DISTLIMIT'
  426. useTarget : bpy.props.BoolProperty(default=True)
  427. def init(self, context):
  428. self.inputs.new ('RelationshipSocket', "Input Relationship")
  429. self.inputs.new ('FloatFactorSocket', "Head/Tail")
  430. self.inputs.new ('BooleanSocket', "UseBBone")
  431. self.inputs.new ('FloatSocket', "Distance")
  432. self.inputs.new ('EnumLimitMode', "Clamp Region")
  433. self.inputs.new ('BooleanSocket', "Affect Transform")
  434. self.inputs.new ('TransformSpaceSocket', "Owner Space")
  435. self.inputs.new ('TransformSpaceSocket', "Target Space")
  436. self.inputs.new ('FloatFactorSocket', "Influence")
  437. self.inputs.new ('xFormSocket', "Target")
  438. self.inputs.new ('EnableSocket', "Enable")
  439. #
  440. self.outputs.new('RelationshipSocket', "Output Relationship")
  441. class LinkTransformationNode(Node, LinkNode):
  442. '''A node representing Transformation (Constraint)'''
  443. bl_idname = 'LinkTransformation'
  444. bl_label = "Transformation"
  445. bl_icon = 'CON_TRANSFORM'
  446. useTarget : bpy.props.BoolProperty(default=True)
  447. def init(self, context):
  448. hide_me = []
  449. self.inputs.new ('RelationshipSocket', "Input Relationship")
  450. self.inputs.new ('xFormSocket', "Target")
  451. self.inputs.new ('TransformSpaceSocket', "Owner Space")
  452. self.inputs.new ('TransformSpaceSocket', "Target Space")
  453. self.inputs.new ('BooleanSocket', "Extrapolate")
  454. self.inputs.new ('EnumTransformationMap', "Map From")
  455. hide_me.append( self.inputs.new ('EnumTransformationRotationMode', "Rotation Mode"))
  456. self.inputs.new ('FloatSocket', "X Min From")
  457. self.inputs.new ('FloatSocket', "X Max From")
  458. self.inputs.new ('FloatSocket', "Y Min From")
  459. self.inputs.new ('FloatSocket', "Y Max From")
  460. self.inputs.new ('FloatSocket', "Z Min From")
  461. self.inputs.new ('FloatSocket', "Z Max From")
  462. self.inputs.new ('EnumTransformationMap', "Map To")
  463. hide_me.append( self.inputs.new ('EnumTransformationRotationOrder', "Rotation Order"))
  464. self.inputs.new ('EnumTransformationAxes', "X Source Axis")
  465. self.inputs.new ('FloatSocket', "X Min To")
  466. self.inputs.new ('FloatSocket', "X Max To")
  467. self.inputs.new ('EnumTransformationAxes', "Y Source Axis")
  468. self.inputs.new ('FloatSocket', "Y Min To")
  469. self.inputs.new ('FloatSocket', "Y Max To")
  470. self.inputs.new ('EnumTransformationAxes', "Z Source Axis")
  471. self.inputs.new ('FloatSocket', "Z Min To")
  472. self.inputs.new ('FloatSocket', "Z Max To")
  473. self.inputs.new ('EnumTransformationTranslationMixMode', "Mix Mode (Translation)")
  474. hide_me.append( self.inputs.new ('EnumTransformationRotationMixMode', "Mix Mode (Rotation)"))
  475. hide_me.append( self.inputs.new ('EnumTransformationScaleMixMode', "Mix Mode (Scale)"))
  476. self.inputs.new ('FloatFactorSocket', "Influence")
  477. self.inputs.new ('EnableSocket', "Enable")
  478. #
  479. self.outputs.new('RelationshipSocket', "Output Relationship")
  480. for s in hide_me:
  481. s.hide = True
  482. def display_update(self, parsed_tree, context):
  483. node_tree = context.space_data.path[0].node_tree
  484. nc = parsed_tree.get(get_signature_from_edited_tree(self, context))
  485. if nc:
  486. if nc.evaluate_input("Map From") == "ROTATION":
  487. self.inputs["Rotation Mode"].hide=False
  488. else:
  489. self.inputs["Rotation Mode"].hide=True
  490. if nc.evaluate_input("Map To") == "TRANSLATION":
  491. self.inputs["Rotation Order"].hide=True
  492. self.inputs["Mix Mode (Translation)"].hide=False
  493. self.inputs["Mix Mode (Rotation)"].hide=True
  494. self.inputs["Mix Mode (Scale)"].hide=True
  495. elif nc.evaluate_input("Map To") == "ROTATION":
  496. self.inputs["Rotation Order"].hide=False
  497. self.inputs["Mix Mode (Translation)"].hide=True
  498. self.inputs["Mix Mode (Rotation)"].hide=False
  499. self.inputs["Mix Mode (Scale)"].hide=True
  500. elif nc.evaluate_input("Map To") == "SCALE":
  501. self.inputs["Rotation Order"].hide=True
  502. self.inputs["Mix Mode (Translation)"].hide=True
  503. self.inputs["Mix Mode (Rotation)"].hide=True
  504. self.inputs["Mix Mode (Scale)"].hide=False
  505. class LinkArmatureNode(Node, LinkNode):
  506. """A node representing Blender's Armature Constraint"""
  507. bl_idname = "LinkArmature"
  508. bl_label = "Armature (Constraint)"
  509. bl_icon = "CON_ARMATURE"
  510. def init(self, context):
  511. self.inputs.new ("RelationshipSocket", "Input Relationship")
  512. self.inputs.new("BooleanSocket", "Preserve Volume")
  513. self.inputs.new("BooleanSocket", "Use Envelopes")
  514. self.inputs.new("BooleanSocket", "Use Current Location")
  515. self.inputs.new("FloatSocket", "Influence")
  516. self.inputs.new ('EnableSocket', "Enable")
  517. self.outputs.new("RelationshipSocket", "Output Relationship")
  518. def traverse(self, socket):
  519. return default_traverse(self,socket)
  520. def draw_buttons(self, context, layout):
  521. layout.operator( 'mantis.link_armature_node_add_target' )
  522. if (len(self.inputs) > 6):
  523. layout.operator( 'mantis.link_armature_node_remove_target' )
  524. else:
  525. layout.label(text="")
  526. class LinkSplineIKNode(Node, LinkNode):
  527. """"A node representing Spline IK"""
  528. bl_idname = "LinkSplineIK"
  529. bl_label = "Spline IK"
  530. bl_icon = "CON_SPLINEIK"
  531. def init(self, context):
  532. self.inputs.new ("RelationshipSocket", "Input Relationship")
  533. self.inputs.new("xFormSocket", "Target")
  534. self.inputs.new("IntSocket", "Chain Length")
  535. self.inputs.new("BooleanSocket", "Even Divisions")
  536. self.inputs.new("BooleanSocket", "Chain Offset")
  537. self.inputs.new("BooleanSocket", "Use Curve Radius")
  538. self.inputs.new("EnumYScaleMode", "Y Scale Mode")
  539. self.inputs.new("EnumXZScaleMode", "XZ Scale Mode")
  540. self.inputs.new("BooleanSocket", "Use Original Scale")
  541. self.inputs.new("FloatSocket", "Influence")
  542. self.outputs.new("RelationshipSocket", "Output Relationship")
  543. def traverse(self, socket):
  544. return default_traverse(self,socket)
  545. # DRIVERS!!
  546. class LinkDrivenParameterNode(Node, LinkNode):
  547. """Represents a driven parameter in the downstream xForm node."""
  548. bl_idname = "LinkDrivenParameter"
  549. bl_label = "Driven Parameter"
  550. bl_icon = "CONSTRAINT_BONE"
  551. def init(self, context):
  552. self.inputs.new ( "RelationshipSocket", "Input Relationship" )
  553. self.inputs.new ( "DriverSocket", "Driver" )
  554. self.inputs.new ( "ParameterStringSocket", "Parameter" )
  555. self.inputs.new ( "IntSocket", "Index" )
  556. self.inputs.new ('EnableSocket', "Enable")
  557. #
  558. self.outputs.new( "RelationshipSocket", "Output Relationship" )
  559. def traverse(self, socket):
  560. return default_traverse(self,socket)