node_container_classes.py 86 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125
  1. # generic node classes
  2. #everything here sucks and is dumb and needs renaiming
  3. # this is stupid, lol
  4. def TellClasses():
  5. # xForm
  6. return [ xFormRoot,
  7. xFormArmature,
  8. xFormBone,
  9. # special
  10. LinkInherit,
  11. # copy
  12. LinkCopyLocation,
  13. LinkCopyRotation,
  14. LinkCopyScale,
  15. LinkCopyTransforms,
  16. # limit
  17. LinkLimitLocation,
  18. LinkLimitRotation,
  19. LinkLimitScale,
  20. LinkLimitDistance,
  21. # tracking
  22. LinkStretchTo,
  23. LinkDampedTrack,
  24. LinkLockedTrack,
  25. LinkTrackTo,
  26. #misc
  27. LinkInheritConstraint,
  28. # IK
  29. LinkInverseKinematics,
  30. # utility
  31. InputFloat,
  32. InputVector,
  33. InputBoolean,
  34. InputBooleanThreeTuple,
  35. InputRotationOrder,
  36. InputTransformSpace,
  37. InputString,
  38. InputQuaternion,
  39. InputQuaternionAA,
  40. InputMatrix,
  41. ]
  42. #kinda a dumb way to do this but it werks so whatever
  43. # have these so far
  44. # simple nodes:
  45. # InputFloatNode,
  46. # InputVectorNode,
  47. # InputBooleanNode,
  48. # InputBooleanThreeTupleNode,
  49. # InputRotationOrderNode,
  50. # InputTransformSpaceNode,
  51. # InputStringNode,
  52. # InputQuaternionNode,
  53. # InputQuaternionNodeAA,
  54. # InputMatrixNode,
  55. # xForm nodes:
  56. # xFormNullNode,
  57. # xFormBoneNode,
  58. # xFormRootNode,
  59. # xFormArmatureNode,
  60. # Link nodes:
  61. # LinkInheritNode,
  62. # LinkInverseKinematics,
  63. # LinkCopyLocationNode,
  64. # LinkCopyRotationNode,
  65. # LinkCopyScaleNode,
  66. # LinkInheritConstraintNode,
  67. # LinkCopyTransformNode,
  68. # LinkStretchToNode,
  69. # LinkDampedTrackNode,
  70. # LinkLockedTrackNode,
  71. # LinkTrackToNode,
  72. # LinkLimitLocationNode,
  73. # LinkLimitScaleNode,
  74. # LinkLimitRotationNode,
  75. # LinkLimitDistanceNode,]
  76. #eventually add this:
  77. # def print_to_mantis_script():
  78. # #gonna eventually make this into a script
  79. # # that can be written and read from a text file
  80. # # and loaded into the interpretor
  81. # pass
  82. #
  83. # DO THIS:
  84. # each node should have a name or UUID, since there must be a way to
  85. # associate them with the lines that are read from the input-graph
  86. # actually I cna and should just use the signature, since it can gimme
  87. # any prototype node I need, and it encodes relationships, too.
  88. def fill_parameters(node_container, node_prototype):
  89. from .utilities import to_mathutils_value
  90. for key, value in node_container.parameters.items():
  91. node_socket = node_prototype.inputs.get(key)
  92. if not node_socket:
  93. #maybe the node socket has no name
  94. if ( ( len(node_prototype.inputs) == 0) and ( len(node_prototype.outputs) == 1) ):
  95. # this is a simple input node.
  96. node_socket = node_prototype.outputs[0]
  97. elif key == 'Mute':
  98. node_container.parameters[key] = node_prototype.mute
  99. continue
  100. else: # really don't know!
  101. raise RuntimeError("No node socket found for " + key + " when filling out node parameters.")
  102. continue
  103. if node_socket.bl_idname in ['RelationshipSocket', 'xFormSocket']:
  104. continue
  105. elif hasattr(node_socket, "default_value"):
  106. default_value_type = type(node_socket.default_value)
  107. #print (default_value_type)
  108. math_val = to_mathutils_value(node_socket)
  109. if math_val:
  110. node_container.parameters[key] = math_val
  111. # maybe we can use it directly.. ?
  112. elif ( (default_value_type == str) or (default_value_type == bool) or
  113. (default_value_type == float) or (default_value_type == int) ):
  114. node_container.parameters[key] = node_socket.default_value
  115. # HACK: there should be no sets, I think, but...
  116. elif default_value_type == set:
  117. node_container.parameters[key] = node_socket.default_value
  118. # TODO: make this make sense sometime in the future!
  119. # There should not be any sets!
  120. else:
  121. raise RuntimeError("No value found for " + key + " when filling out node parameters for " + node_prototype.name)
  122. else:
  123. print (key, node_socket)
  124. # do: remove these from parameters maybe
  125. # since they are always None if not connected
  126. # for key, value in node_container.parameters.items():
  127. # if value:
  128. # print (key, value)
  129. def evaluate_input(node_container, input_name):
  130. # for simple cases
  131. trace = trace_single_line(node_container, input_name)
  132. prop = trace[0][-1].parameters.get(trace[1].to_socket)
  133. # WHY doesn't this work for the Matrix inputs .. ?
  134. return prop
  135. def trace_node_lines(node_container):
  136. """ Tells the depth of a node within the node tree. """
  137. node_lines = []
  138. if hasattr(node_container, "inputs"):
  139. for key, socket in node_container.inputs.items():
  140. # Recrusive search through the tree.
  141. # * checc each relevant input socket in the node
  142. # * for EACH input, find the node it's connected to
  143. # * repeat from here until you get all the lines
  144. if ( ( key in ["Relationship", "Parent", "Input Relationship", "Target"])
  145. and (socket.is_connected) ):
  146. # it is necesary to check the key because of Link nodes,
  147. # which don't really traverse like normal.
  148. # TODO: see if I can refactor this to make it traverse
  149. other = socket.from_node
  150. if (other):
  151. other_lines = trace_node_lines(other)
  152. if not other_lines:
  153. node_lines.append([other])
  154. for line in other_lines:
  155. node_lines.append( [other] + line )
  156. return node_lines
  157. def trace_single_line(node_container, input_name):
  158. """ Tells the depth of a node within the node tree. """
  159. nodes = [node_container]
  160. if hasattr(node_container, "inputs"):
  161. # Trace a single line
  162. if (socket := node_container.inputs.get(input_name) ):
  163. while (socket.is_connected):
  164. other = socket.from_node.outputs.get(socket.from_socket)
  165. if (other):
  166. socket = other
  167. if socket.can_traverse:
  168. socket = socket.traverse_target
  169. nodes.append(socket.to_node)
  170. else: # this is an output.
  171. nodes.append(socket.from_node)
  172. break
  173. else:
  174. break
  175. return nodes, socket
  176. # this is same as the other, just flip from/to and in/out
  177. def trace_single_line_up(node_container, output_name):
  178. """ Tells the depth of a node within the node tree. """
  179. nodes = [node_container]
  180. if hasattr(node_container, "outputs"):
  181. # Trace a single line
  182. if (socket := node_container.outputs.get(output_name) ):
  183. while (socket.is_connected):
  184. other = socket.to_node.inputs.get(socket.to_socket)
  185. if (other):
  186. socket = other
  187. if socket.can_traverse:
  188. socket = socket.traverse_target
  189. nodes.append(socket.from_node)
  190. else: # this is an input.
  191. nodes.append(socket.to_node)
  192. break
  193. else:
  194. break
  195. return nodes, socket
  196. def node_depth(node_container):
  197. maxlen = 0
  198. for nodes in trace_node_lines(node_container):
  199. if (len(nodes) > maxlen):
  200. maxlen = len(nodes)
  201. return maxlen
  202. def get_parent(node_container):
  203. node_line, socket = trace_single_line(node_container, "Relationship")
  204. parent_nc = None
  205. for i in range(len(node_line)):
  206. print (node_line[i])
  207. # check each of the possible parent types.
  208. if ( isinstance(node_line[ i ], LinkInherit) ):
  209. try: # it's the next one
  210. return node_line[ i + 1 ]
  211. except IndexError: # if there is no next one...
  212. return None # then there's no parent!
  213. return None
  214. # TO DO!
  215. #
  216. # make this do shorthand parenting - if no parent, then use World
  217. # if the parent node is skipped, use the previous node (an xForm)
  218. # with default settings.
  219. # it is OK to generate a new, "fake" node container for this!
  220. def get_target_and_subtarget(node_container, constraint, input_name = "Target"):
  221. from bpy.types import PoseBone, Object
  222. subtarget = ''; target = node_container.evaluate_input(input_name)
  223. if target:
  224. if (isinstance(target.bGetObject(), PoseBone)):
  225. subtarget = target.bGetObject().name
  226. target = target.bGetParentArmature()
  227. elif (isinstance(target.bGetObject(), Object) ):
  228. target = target.bGetObject()
  229. else:
  230. raise RuntimeError("Cannot interpret constraint target!")
  231. if (input_name == 'Target'): # this is sloppy, but it werks
  232. constraint.target, constraint.subtarget = target, subtarget
  233. elif (input_name == 'Pole Target'):
  234. constraint.pole_target, constraint.pole_subtarget = target, subtarget
  235. class NodeSocket:
  236. # this is not meant to be a particularly robust class
  237. # e.g., there will be no disconnect() method since it isn't needed
  238. # I just wanna have something persistent (an object)
  239. # I'd perfer to use pointers and structs, whatever
  240. is_input = False
  241. is_connected = False
  242. from_node = None
  243. to_node = None
  244. from_socket = None
  245. to_socket = None
  246. can_traverse = False
  247. traverse_target = None
  248. def __init__(self, is_input = False,
  249. from_socket = None, to_socket = None,
  250. from_node = None, to_node = None,
  251. traverse_target = None):
  252. self.from_socket = from_socket
  253. self.to_socket = to_socket
  254. self.from_node = from_node
  255. self.to_node = to_node
  256. self.is_input = is_input
  257. if (self.is_input and (self.from_node or self.from_socket)):
  258. self.is_connected = True
  259. elif ( not self.is_input and (self.to_node or self.to_socket)):
  260. self.is_connected = True
  261. self.set_traverse_target(traverse_target)
  262. def connect(self, node, socket):
  263. if (self.is_input):
  264. self.from_node = node
  265. self.from_socket = socket
  266. else:
  267. self.to_node = node
  268. self.to_socket = socket
  269. self.is_connected = True
  270. def set_traverse_target(self, traverse_target):
  271. if (traverse_target):
  272. self.traverse_target = traverse_target
  273. self.can_traverse = True
  274. def __repr__(self):
  275. if self.is_input:
  276. return ( self.to_node.__repr__() + "::" + self.to_socket )
  277. else:
  278. return (self.from_node.__repr__() + "::" + self.from_socket)
  279. #*#-------------------------------#++#-------------------------------#*#
  280. # X - F O R M N O D E S
  281. #*#-------------------------------#++#-------------------------------#*#
  282. # class xFormNull:
  283. # '''A node representing an Empty object'''
  284. # inputs =
  285. # {
  286. # "Name":None,
  287. # "Rotation Order":None,
  288. # "Matrix":None,
  289. # "Relationship":None,
  290. # }
  291. # outputs =
  292. # {
  293. # "xFormOut":None,
  294. # }
  295. # parameters =
  296. # {
  297. # "Name":None,
  298. # "Rotation Order":None,
  299. # "Matrix":None,
  300. # "Relationship":None,
  301. # }
  302. # def evaluate_input(self, input):
  303. # pass
  304. # def instantiate_blender_object(self):
  305. # pass
  306. # for whatever reason, the above isn't implemented yet in the node-tree
  307. # so I'm not implementing it here, either
  308. class xFormRoot:
  309. '''A node representing the root of the scene.'''
  310. def __init__(self, signature, base_tree):
  311. self.base_tree=base_tree
  312. self.signature = signature
  313. self.inputs = {}
  314. self.outputs = {"xForm Out":NodeSocket(from_socket="xForm Out", from_node = self),}
  315. self.parameters = {}
  316. self.links = {} # leave this empty for now!
  317. self.node_type = 'XFORM'
  318. def init_to_node_line(line,):
  319. pass
  320. def evaluate_input(self, input_name):
  321. return "ROOT"
  322. def bExecute(self, bContext = None,):
  323. pass
  324. def __repr__(self):
  325. return self.signature.__repr__()
  326. def fill_parameters(self, node_prototype):
  327. fill_parameters(self, node_prototype)
  328. class xFormArmature:
  329. '''A node representing an armature object'''
  330. bObject = None
  331. def __init__(self, signature, base_tree):
  332. self.base_tree=base_tree
  333. self.executed = False
  334. self.signature = signature
  335. self.inputs = {
  336. "Name" : NodeSocket(is_input = True, to_socket = "Name", to_node = self),
  337. "Rotation Order" : NodeSocket(is_input = True, to_socket = "Rotation Order", to_node = self),
  338. "Matrix" : NodeSocket(is_input = True, to_socket = "Matrix", to_node = self),
  339. "Relationship" : NodeSocket(is_input = True, to_socket = "Relationship", to_node = self),
  340. }
  341. self.outputs = {
  342. "xForm Out" : NodeSocket(from_socket="xForm Out", from_node = self),
  343. }
  344. self.parameters = {
  345. "Name":None,
  346. "Rotation Order":None,
  347. "Matrix":None,
  348. "Relationship":None,
  349. }
  350. self.links = {} # leave this empty for now!
  351. # now set up the traverse target...
  352. self.inputs["Relationship"].set_traverse_target(self.outputs["xForm Out"])
  353. self.outputs["xForm Out"].set_traverse_target(self.inputs["Relationship"])
  354. self.node_type = 'XFORM'
  355. def evaluate_input(self, input_name):
  356. return evaluate_input(self, input_name)
  357. def bExecute(self, bContext = None,):
  358. from .utilities import get_node_prototype
  359. import bpy
  360. if (not isinstance(bContext, bpy.types.Context)):
  361. raise RuntimeError("Incorrect context")
  362. name = self.evaluate_input("Name")
  363. matrix = self.evaluate_input('Matrix')
  364. #check if an object by the name exists
  365. if (name) and (ob := bpy.data.objects.get(name)):
  366. for pb in ob.pose.bones:
  367. # clear it, even after deleting the edit bones,
  368. # if we create them again the pose bones will be reused
  369. while (pb.constraints):
  370. pb.constraints.remove(pb.constraints[-1])
  371. pb.location = (0,0,0)
  372. pb.rotation_euler = (0,0,0)
  373. pb.rotation_quaternion = (1.0,0,0,0)
  374. pb.rotation_axis_angle = (0,0,1.0,0)
  375. pb.scale = (1.0,1.0,1.0)
  376. else:
  377. # Create the Object
  378. ob = bpy.data.objects.new(name, bpy.data.armatures.new(name)) #create ob
  379. if (ob.name != name):
  380. raise RuntimeError("Could not create xForm object", name)
  381. self.bObject = ob.name
  382. ob.matrix_world = matrix
  383. # first, get the parent object
  384. parent_node = get_parent(self)
  385. if hasattr(parent_node, "bObject"):
  386. # this won't work of course, TODO
  387. self.bObject.parent = parent_node.bObject
  388. # Link to Scene:
  389. if (ob.name not in bContext.view_layer.active_layer_collection.collection.objects):
  390. bContext.view_layer.active_layer_collection.collection.objects.link(ob)
  391. #self.bParent(bContext)
  392. # Finalize the action
  393. # prevAct = bContext.view_layer.objects.active
  394. bContext.view_layer.objects.active = ob
  395. bpy.ops.object.mode_set(mode='EDIT')
  396. print ("Changing Armature Mode to EDIT")
  397. # clear it
  398. while (len(ob.data.edit_bones) > 0):
  399. ob.data.edit_bones.remove(ob.data.edit_bones[0])
  400. # bContext.view_layer.objects.active = prevAct
  401. print ("Created Armature object: \""+ ob.name +"\"")
  402. self.executed = True
  403. # # not used yet
  404. # #
  405. # def bFinalize(self, bContext = None):
  406. # import bpy
  407. # ob = self.bGetObject()
  408. # prevAct = bContext.view_layer.objects.active
  409. # bContext.view_layer.objects.active = ob
  410. # bpy.ops.object.mode_set(mode='OBJECT')
  411. # print ("Changing Armature Mode to OBJECT")
  412. # bContext.view_layer.objects.active = prevAct
  413. def bGetObject(self, mode = ''):
  414. import bpy
  415. return bpy.data.objects[self.bObject]
  416. def __repr__(self):
  417. return self.signature.__repr__()
  418. def fill_parameters(self, node_prototype):
  419. fill_parameters(self, node_prototype)
  420. class xFormBone:
  421. '''A node representing a bone in an armature'''
  422. # DO: make a way to identify which armature this belongs to
  423. def __init__(self, signature, base_tree):
  424. self.base_tree=base_tree
  425. self.executed = False
  426. self.signature = signature
  427. self.inputs = {
  428. "Name" : NodeSocket(is_input = True, to_socket = "Name", to_node = self,),
  429. "Rotation Order" : NodeSocket(is_input = True, to_socket = "Rotation Order", to_node = self,),
  430. "Matrix" : NodeSocket(is_input = True, to_socket = "Matrix", to_node = self,),
  431. "Relationship" : NodeSocket(is_input = True, to_socket = "Relationship", to_node = self,),
  432. # IK settings
  433. "IK Stretch" : NodeSocket(is_input = True, to_socket = "IK Stretch", to_node = self,),
  434. "Lock IK" : NodeSocket(is_input = True, to_socket = "Lock IK", to_node = self,),
  435. "IK Stiffness" : NodeSocket(is_input = True, to_socket = "IK Stiffness", to_node = self,),
  436. "Limit IK" : NodeSocket(is_input = True, to_socket = "Limit IK", to_node = self,),
  437. "X Min" : NodeSocket(is_input = True, to_socket = "X Min", to_node = self,),
  438. "X Max" : NodeSocket(is_input = True, to_socket = "X Max", to_node = self,),
  439. "Y Min" : NodeSocket(is_input = True, to_socket = "Y Min", to_node = self,),
  440. "Y Max" : NodeSocket(is_input = True, to_socket = "Y Max", to_node = self,),
  441. "Z Min" : NodeSocket(is_input = True, to_socket = "Z Min", to_node = self,),
  442. "Z Max" : NodeSocket(is_input = True, to_socket = "Z Max", to_node = self,),
  443. }
  444. self.outputs = {
  445. "xForm Out" : NodeSocket(from_socket = "xForm Out", from_node = self),
  446. }
  447. self.parameters = {
  448. "Name":None,
  449. "Rotation Order":None,
  450. "Matrix":None,
  451. "Relationship":None,
  452. # IK settings
  453. "IK Stretch":None,
  454. "Lock IK":None,
  455. "IK Stiffness":None,
  456. "Limit IK":None,
  457. "X Min":None,
  458. "X Max":None,
  459. "Y Min":None,
  460. "Y Max":None,
  461. "Z Min":None,
  462. "Z Max":None,
  463. }
  464. self.links = {} # leave this empty for now!
  465. # now set up the traverse target...
  466. self.inputs["Relationship"].set_traverse_target(self.outputs["xForm Out"])
  467. self.outputs["xForm Out"].set_traverse_target(self.inputs["Relationship"])
  468. self.node_type = 'XFORM'
  469. def evaluate_input(self, input_name):
  470. return evaluate_input(self, input_name)
  471. def __repr__(self):
  472. return self.signature.__repr__()
  473. def fill_parameters(self, node_prototype):
  474. fill_parameters(self, node_prototype)
  475. def bGetParentArmature(self):
  476. finished = False
  477. if (trace := trace_single_line(self, "Relationship")[0] ) :
  478. for i in range(len(trace)):
  479. # have to look in reverse, actually
  480. if ( isinstance(trace[ i ], xFormArmature ) ):
  481. return trace[ i ].bGetObject()
  482. return None
  483. #should do the trick...
  484. def bSetParent(self, eb):
  485. from bpy.types import EditBone
  486. parent_nc = get_parent(self)
  487. parent = parent_nc.bGetObject(mode = 'EDIT')
  488. if isinstance(parent, EditBone):
  489. print (parent.name)
  490. eb.parent = parent
  491. else:
  492. print(parent)
  493. # otherwise, no need to do anything.
  494. def bExecute(self, bContext = None,): #possibly will need to pass context?
  495. import bpy
  496. from mathutils import Vector
  497. if (not isinstance(bContext, bpy.types.Context)):
  498. raise RuntimeError("Incorrect context")
  499. xF = self.bGetParentArmature()
  500. name = self.evaluate_input("Name")
  501. matrix = self.evaluate_input("Matrix")
  502. length = matrix[3][3]
  503. matrix[3][3] = 1.0 # set this bacc, could cause problems otherwise.
  504. if (xF):
  505. if (xF.mode != "EDIT"):
  506. raise RuntimeError("Armature Object Not in Edit Mode, exiting...")
  507. else:
  508. raise RuntimeError("No armature object to add bone to.")
  509. #
  510. # Create the Object
  511. d = xF.data
  512. eb = d.edit_bones.new(name)
  513. if (eb.name != name):
  514. raise RuntimeError("Could not create bone ", name, "; Perhaps there is a duplicate bone name in the node tree?")
  515. eb.matrix = matrix.copy()
  516. tailoffset = Vector((0,length,0)) #Vector((0,self.tailoffset, 0))
  517. tailoffset = matrix.copy().to_3x3() @ tailoffset
  518. eb.tail = eb.head + tailoffset
  519. if (eb.name != name):
  520. raise RuntimeError("Could not create edit bone: ", name)
  521. self.bObject = eb.name
  522. # The bone should have relationships going in at this point.
  523. self.bSetParent(eb)
  524. return
  525. self.bParent(bContext)
  526. print ("Created Bone: \""+ eb.name+ "\" in \"" + self.bGetParentArmature().name +"\"")
  527. self.executed = True
  528. def bFinalize(self, bContext = None):
  529. # prevAct = bContext.view_layer.objects.active
  530. # bContext.view_layer.objects.active = ob
  531. # bpy.ops.object.mode_set(mode='OBJECT')
  532. # bContext.view_layer.objects.active = prevAct
  533. #
  534. #get relationship
  535. # ensure we have a pose bone...
  536. # set the ik parameters
  537. pass
  538. def bGetObject(self, mode = 'POSE'):
  539. if (mode == 'EDIT'):
  540. try:
  541. return self.bGetParentArmature().data.edit_bones[self.bObject]
  542. except KeyError:
  543. return None
  544. if (mode == 'OBJECT'):
  545. try:
  546. return self.bGetParentArmature().data.bones[self.bObject]
  547. except KeyError:
  548. return None
  549. if (mode == 'POSE'):
  550. try:
  551. return self.bGetParentArmature().pose.bones[self.bObject]
  552. except KeyError:
  553. return None
  554. #*#-------------------------------#++#-------------------------------#*#
  555. # L I N K N O D E S
  556. #*#-------------------------------#++#-------------------------------#*#
  557. class LinkInherit:
  558. '''A node representing inheritance'''
  559. def __init__(self, signature, base_tree):
  560. self.base_tree=base_tree
  561. self.signature = signature
  562. self.inputs = {
  563. "Parent" : NodeSocket(is_input = True, to_socket = "Parent", to_node = self,),
  564. # bone only:
  565. "Inherit Rotation" : NodeSocket(is_input = True, to_socket = "Inherit Rotation", to_node = self,),
  566. "Inherit Scale" : NodeSocket(is_input = True, to_socket = "Inherit Scale", to_node = self,),
  567. "Connected" : NodeSocket(is_input = True, to_socket = "Connected", to_node = self,),
  568. }
  569. self.outputs = { "Inheritance" : NodeSocket(from_socket = "Inheritance", from_node = self) }
  570. self.parameters = {
  571. "Parent":None,
  572. # bone only:
  573. "Inherit Rotation":None,
  574. "Inherit Scale":None,
  575. "Connected":None,
  576. "Mute":None,
  577. }
  578. self.links = {} # leave this empty for now!
  579. # now set up the traverse target...
  580. self.inputs["Parent"].set_traverse_target(self.outputs["Inheritance"])
  581. self.outputs["Inheritance"].set_traverse_target(self.inputs["Parent"])
  582. self.node_type = 'LINK'
  583. def evaluate_input(self, input_name):
  584. return evaluate_input(self, input_name)
  585. def bExecute(self, bContext = None,):
  586. # this is handled by the xForm objects, since it isn't really
  587. # a constraint.
  588. pass
  589. def __repr__(self):
  590. return self.signature.__repr__()
  591. def fill_parameters(self, node_prototype):
  592. fill_parameters(self, node_prototype)
  593. class LinkCopyLocation:
  594. '''A node representing Copy Location'''
  595. def __init__(self, signature, base_tree):
  596. self.base_tree=base_tree
  597. self.signature = signature
  598. self.inputs = {
  599. "Input Relationship" : NodeSocket(is_input = True, to_socket = "Input Relationship", to_node = self,),
  600. "Head/Tail" : NodeSocket(is_input = True, to_socket = "Head/Tail", to_node = self,),
  601. "UseBBone" : NodeSocket(is_input = True, to_socket = "UseBBone", to_node = self,),
  602. "Axes" : NodeSocket(is_input = True, to_socket = "Axes", to_node = self,),
  603. "Invert" : NodeSocket(is_input = True, to_socket = "Invert", to_node = self,),
  604. "Target Space" : NodeSocket(is_input = True, to_socket = "Target Space", to_node = self,),
  605. "Owner Space" : NodeSocket(is_input = True, to_socket = "Owner Space", to_node = self,),
  606. "Influence" : NodeSocket(is_input = True, to_socket = "Influence", to_node = self,),
  607. "Target" : NodeSocket(is_input = True, to_socket = "Target", to_node = self,), }
  608. self.outputs = {
  609. "Output Relationship" : NodeSocket(from_socket = "Output Relationship", from_node=self) }
  610. self.parameters = {
  611. "Input Relationship":None,
  612. "Head/Tail":None,
  613. "UseBBone":None,
  614. "Axes":None,
  615. "Invert":None,
  616. "Target Space":None,
  617. "Owner Space":None,
  618. "Influence":None,
  619. "Target":None,
  620. "Mute":None, }
  621. # now set up the traverse target...
  622. self.inputs["Input Relationship"].set_traverse_target(self.outputs["Output Relationship"])
  623. self.outputs["Output Relationship"].set_traverse_target(self.inputs["Input Relationship"])
  624. self.node_type = 'LINK'
  625. def evaluate_input(self, input_name):
  626. if (input_name == 'Target'):
  627. socket = self.inputs.get(input_name)
  628. return socket.from_node
  629. else:
  630. return evaluate_input(self, input_name)
  631. def GetxForm(self):
  632. # I don't think I have a function for getting children yet!
  633. trace = trace_single_line_up(self, "Output Relationship")
  634. for node in trace[0]:
  635. if (node.__class__ in [xFormRoot, xFormArmature, xFormBone]):
  636. return node
  637. return None
  638. def bExecute(self, context):
  639. c = self.GetxForm().bGetObject().constraints.new('COPY_LOCATION')
  640. get_target_and_subtarget(self, c)
  641. c.head_tail = self.evaluate_input("Head/Tail")
  642. c.use_bbone_shape = self.evaluate_input("UseBBone")
  643. c.owner_space = self.evaluate_input("Owner Space")
  644. c.target_space = self.evaluate_input("Target Space")
  645. c.invert_x = self.evaluate_input("Invert")[0]
  646. c.invert_y = self.evaluate_input("Invert")[1]
  647. c.invert_z = self.evaluate_input("Invert")[2]
  648. c.use_x = self.evaluate_input("Axes")[0]
  649. c.use_y = self.evaluate_input("Axes")[1]
  650. c.use_z = self.evaluate_input("Axes")[2]
  651. c.influence = self.evaluate_input("Influence")
  652. print ("Creating Copy Location Constraint for bone: \""+ self.GetxForm().bGetObject().name + "\"")
  653. if self.parameters["Mute"]:
  654. c.enabled = False
  655. def __repr__(self):
  656. return self.signature.__repr__()
  657. def fill_parameters(self, node_prototype):
  658. fill_parameters(self, node_prototype)
  659. class LinkCopyRotation:
  660. '''A node representing Copy Rotation'''
  661. def __init__(self, signature, base_tree):
  662. self.base_tree=base_tree
  663. self.signature = signature
  664. self.inputs = {
  665. "Input Relationship" : NodeSocket(is_input = True, to_socket = "Input Relationship", to_node = self,),
  666. "RotationOrder" : NodeSocket(is_input = True, to_socket = "RotationOrder", to_node = self,),
  667. "Rotation Mix" : NodeSocket(is_input = True, to_socket = "Rotation Mix", to_node = self,),
  668. "Axes" : NodeSocket(is_input = True, to_socket = "Axes", to_node = self,),
  669. "Invert" : NodeSocket(is_input = True, to_socket = "Invert", to_node = self,),
  670. "Target Space" : NodeSocket(is_input = True, to_socket = "Target Space", to_node = self,),
  671. "Owner Space" : NodeSocket(is_input = True, to_socket = "Owner Space", to_node = self,),
  672. "Influence" : NodeSocket(is_input = True, to_socket = "Influence", to_node = self,),
  673. "Target" : NodeSocket(is_input = True, to_socket = "Target", to_node = self,), }
  674. self.outputs = {
  675. "Output Relationship" : NodeSocket(from_socket = "Output Relationship", from_node=self) }
  676. self.parameters = {
  677. "Input Relationship":None,
  678. "RotationOrder":None,
  679. "Rotation Mix":None,
  680. "Axes":None,
  681. "Invert":None,
  682. "Target Space":None,
  683. "Owner Space":None,
  684. "Influence":None,
  685. "Target":None,
  686. "Mute":None, }
  687. # now set up the traverse target...
  688. self.inputs["Input Relationship"].set_traverse_target(self.outputs["Output Relationship"])
  689. self.outputs["Output Relationship"].set_traverse_target(self.inputs["Input Relationship"])
  690. self.node_type = 'LINK'
  691. def evaluate_input(self, input_name):
  692. if (input_name == 'Target'):
  693. socket = self.inputs.get(input_name)
  694. return socket.from_node
  695. else:
  696. return evaluate_input(self, input_name)
  697. def GetxForm(self):
  698. # I don't think I have a function for getting children yet!
  699. trace = trace_single_line_up(self, "Output Relationship")
  700. for node in trace[0]:
  701. if (node.__class__ in [xFormRoot, xFormArmature, xFormBone]):
  702. return node
  703. return None
  704. def bExecute(self, context):
  705. c = self.GetxForm().bGetObject().constraints.new('COPY_ROTATION')
  706. get_target_and_subtarget(self, c)
  707. rotation_order = self.evaluate_input("RotationOrder")
  708. if ((rotation_order == 'QUATERNION') or (rotation_order == 'AXIS_ANGLE')):
  709. c.euler_order = 'AUTO'
  710. else:
  711. c.euler_order = rotation_order
  712. #c.mix_mode = self.evaluate_input("Rotation Mix")
  713. # kek, deal with this later
  714. # TODO HACK
  715. # dumb enums
  716. c.owner_space = self.evaluate_input("Owner Space")
  717. c.target_space = self.evaluate_input("Target Space")
  718. c.invert_x = self.evaluate_input("Invert")[0]
  719. c.invert_y = self.evaluate_input("Invert")[1]
  720. c.invert_z = self.evaluate_input("Invert")[2]
  721. c.use_x = self.evaluate_input("Axes")[0]
  722. c.use_y = self.evaluate_input("Axes")[1]
  723. c.use_z = self.evaluate_input("Axes")[2]
  724. c.influence = self.evaluate_input("Influence")
  725. print ("Creating Copy Rotation Constraint for bone: \""+ self.GetxForm().bGetObject().name + "\"")
  726. if self.parameters["Mute"]:
  727. c.enabled = False
  728. def __repr__(self):
  729. return self.signature.__repr__()
  730. def fill_parameters(self, node_prototype):
  731. fill_parameters(self, node_prototype)
  732. class LinkCopyScale:
  733. '''A node representing Copy Scale'''
  734. def __init__(self, signature, base_tree):
  735. self.base_tree=base_tree
  736. self.signature = signature
  737. self.inputs = {
  738. "Input Relationship" : NodeSocket(is_input = True, to_socket = "Input Relationship", to_node = self,),
  739. "Offset" : NodeSocket(is_input = True, to_socket = "Offset", to_node = self,),
  740. "Average" : NodeSocket(is_input = True, to_socket = "Average", to_node = self,),
  741. "Additive" : NodeSocket(is_input = True, to_socket = "Additive", to_node = self,),
  742. "Axes" : NodeSocket(is_input = True, to_socket = "Axes", to_node = self,),
  743. #"Invert" : NodeSocket(is_input = True, to_socket = "Invert", to_node = self,),
  744. "Target Space" : NodeSocket(is_input = True, to_socket = "Target Space", to_node = self,),
  745. "Owner Space" : NodeSocket(is_input = True, to_socket = "Owner Space", to_node = self,),
  746. "Influence" : NodeSocket(is_input = True, to_socket = "Influence", to_node = self,),
  747. "Target" : NodeSocket(is_input = True, to_socket = "Target", to_node = self,), }
  748. self.outputs = {
  749. "Output Relationship" : NodeSocket(from_socket = "Output Relationship", from_node=self) }
  750. self.parameters = {
  751. "Input Relationship":None,
  752. "Offset":None,
  753. "Average":None,
  754. "Axes":None,
  755. #"Invert":None,
  756. "Target Space":None,
  757. "Owner Space":None,
  758. "Influence":None,
  759. "Target":None,
  760. "Mute":None,}
  761. # now set up the traverse target...
  762. self.inputs["Input Relationship"].set_traverse_target(self.outputs["Output Relationship"])
  763. self.outputs["Output Relationship"].set_traverse_target(self.inputs["Input Relationship"])
  764. self.node_type = 'LINK'
  765. def evaluate_input(self, input_name):
  766. if (input_name == 'Target'):
  767. socket = self.inputs.get(input_name)
  768. return socket.from_node
  769. else:
  770. return evaluate_input(self, input_name)
  771. def GetxForm(self):
  772. trace = trace_single_line_up(self, "Output Relationship")
  773. for node in trace[0]:
  774. if (node.__class__ in [xFormRoot, xFormArmature, xFormBone]):
  775. return node
  776. return None
  777. def bExecute(self, context):
  778. c = self.GetxForm().bGetObject().constraints.new('COPY_SCALE')
  779. get_target_and_subtarget(self, c)
  780. c.use_offset = self.evaluate_input("Offset")
  781. c.use_make_uniform = self.evaluate_input("Average")
  782. c.owner_space = self.evaluate_input("Owner Space")
  783. c.target_space = self.evaluate_input("Target Space")
  784. c.use_x = self.evaluate_input("Axes")[0]
  785. c.use_y = self.evaluate_input("Axes")[1]
  786. c.use_z = self.evaluate_input("Axes")[2]
  787. c.influence = self.evaluate_input("Influence")
  788. print ("Creating Copy Location Constraint for bone: \""+ self.GetxForm().bGetObject().name + "\"")
  789. if self.parameters["Mute"]:
  790. c.enabled = False
  791. def __repr__(self):
  792. return self.signature.__repr__()
  793. def fill_parameters(self, node_prototype):
  794. fill_parameters(self, node_prototype)
  795. class LinkCopyTransforms:
  796. '''A node representing Copy Transfoms'''
  797. def __init__(self, signature, base_tree):
  798. self.base_tree=base_tree
  799. self.signature = signature
  800. self.inputs = {
  801. "Input Relationship" : NodeSocket(is_input = True, to_socket = "Input Relationship", to_node = self,),
  802. "Head/Tail" : NodeSocket(is_input = True, to_socket = "Head/Tail", to_node = self,),
  803. "UseBBone" : NodeSocket(is_input = True, to_socket = "UseBBone", to_node = self,),
  804. "Additive" : NodeSocket(is_input = True, to_socket = "Additive", to_node = self,),
  805. "Mix" : NodeSocket(is_input = True, to_socket = "Mix", to_node = self,),
  806. "Target Space" : NodeSocket(is_input = True, to_socket = "Target Space", to_node = self,),
  807. "Owner Space" : NodeSocket(is_input = True, to_socket = "Owner Space", to_node = self,),
  808. "Influence" : NodeSocket(is_input = True, to_socket = "Influence", to_node = self,),
  809. "Target" : NodeSocket(is_input = True, to_socket = "Target", to_node = self,), }
  810. self.outputs = {
  811. "Output Relationship" : NodeSocket(from_socket = "Output Relationship", from_node=self) }
  812. self.parameters = {
  813. "Input Relationship":None,
  814. "Head/Tail":None,
  815. "UseBBone":None,
  816. "Mix":None,
  817. "Target Space":None,
  818. "Owner Space":None,
  819. "Influence":None,
  820. "Target":None,
  821. "Mute":None,}
  822. # now set up the traverse target...
  823. self.inputs["Input Relationship"].set_traverse_target(self.outputs["Output Relationship"])
  824. self.outputs["Output Relationship"].set_traverse_target(self.inputs["Input Relationship"])
  825. self.node_type = 'LINK'
  826. def evaluate_input(self, input_name):
  827. if (input_name == 'Target'):
  828. socket = self.inputs.get(input_name)
  829. return socket.from_node
  830. else:
  831. return evaluate_input(self, input_name)
  832. def GetxForm(self):
  833. trace = trace_single_line_up(self, "Output Relationship")
  834. for node in trace[0]:
  835. if (node.__class__ in [xFormRoot, xFormArmature, xFormBone]):
  836. return node
  837. return None
  838. def bExecute(self, context):
  839. c = self.GetxForm().bGetObject().constraints.new('COPY_TRANSFORMS')
  840. get_target_and_subtarget(self, c)
  841. c.head_tail = self.evaluate_input("Head/Tail")
  842. c.use_bbone_shape = self.evaluate_input("UseBBone")
  843. c.mix_mode = self.evaluate_input("Mix")
  844. c.owner_space = self.evaluate_input("Owner Space")
  845. c.target_space = self.evaluate_input("Target Space")
  846. c.influence = self.evaluate_input("Influence")
  847. print ("Creating Copy Transforms Constraint for bone: \""+ self.GetxForm().bGetObject().name + "\"")
  848. if self.parameters["Mute"]:
  849. c.enabled = False
  850. def __repr__(self):
  851. return self.signature.__repr__()
  852. def fill_parameters(self, node_prototype):
  853. fill_parameters(self, node_prototype)
  854. class LinkLimitLocation:
  855. def __init__(self, signature, base_tree):
  856. self.base_tree=base_tree
  857. self.signature = signature
  858. self.inputs = {
  859. "Input Relationship" : NodeSocket(is_input = True, to_socket = "Input Relationship", to_node = self,),
  860. "Use Max X" : NodeSocket(is_input = True, to_socket = "Use Max X", to_node = self,),
  861. "Max X" : NodeSocket(is_input = True, to_socket = "Max X", to_node = self,),
  862. "Use Max Y" : NodeSocket(is_input = True, to_socket = "Use Max Y", to_node = self,),
  863. "Max Y" : NodeSocket(is_input = True, to_socket = "Max Y", to_node = self,),
  864. "Use Max Z" : NodeSocket(is_input = True, to_socket = "Use Max Z", to_node = self,),
  865. "Max Z" : NodeSocket(is_input = True, to_socket = "Max Z", to_node = self,),
  866. "Use Min X" : NodeSocket(is_input = True, to_socket = "Use Min X", to_node = self,),
  867. "Min X" : NodeSocket(is_input = True, to_socket = "Min X", to_node = self,),
  868. "Use Min Y" : NodeSocket(is_input = True, to_socket = "Use Min Y", to_node = self,),
  869. "Min Y" : NodeSocket(is_input = True, to_socket = "Min Y", to_node = self,),
  870. "Use Min Z" : NodeSocket(is_input = True, to_socket = "Use Min Z", to_node = self,),
  871. "Min Z" : NodeSocket(is_input = True, to_socket = "Min Z", to_node = self,),
  872. "Affect Transform" : NodeSocket(is_input = True, to_socket = "Affect Transform", to_node = self,),
  873. "Owner Space" : NodeSocket(is_input = True, to_socket = "Owner Space", to_node = self,),
  874. "Influence" : NodeSocket(is_input = True, to_socket = "Influence", to_node = self,), }
  875. self.outputs = {
  876. "Output Relationship" : NodeSocket(from_socket = "Output Relationship", from_node=self) }
  877. self.parameters = {
  878. "Input Relationship":None,
  879. "Use Max X":None,
  880. "Max X":None,
  881. "Use Max Y":None,
  882. "Max Y":None,
  883. "Use Max Z":None,
  884. "Max Z":None,
  885. "Use Min X":None,
  886. "Min X":None,
  887. "Use Min Y":None,
  888. "Min Y":None,
  889. "Use Min Z":None,
  890. "Min Z":None,
  891. "Affect Transform":None,
  892. "Owner Space":None,
  893. "Influence":None,
  894. "Mute":None,}
  895. # now set up the traverse target...
  896. self.inputs["Input Relationship"].set_traverse_target(self.outputs["Output Relationship"])
  897. self.outputs["Output Relationship"].set_traverse_target(self.inputs["Input Relationship"])
  898. self.node_type = 'LINK'
  899. def evaluate_input(self, input_name):
  900. return evaluate_input(self, input_name)
  901. def GetxForm(self):
  902. trace = trace_single_line_up(self, "Output Relationship")
  903. for node in trace[0]:
  904. if (node.__class__ in [xFormRoot, xFormArmature, xFormBone]):
  905. return node
  906. return None
  907. def bExecute(self, context):
  908. c = self.GetxForm().bGetObject().constraints.new('LIMIT_LOCATION')
  909. #
  910. c.max_x = self.evaluate_input("Max X")
  911. c.max_y = self.evaluate_input("Max Y")
  912. c.max_z = self.evaluate_input("Max Z")
  913. #
  914. c.min_x = self.evaluate_input("Min X")
  915. c.min_y = self.evaluate_input("Min Y")
  916. c.min_z = self.evaluate_input("Min Z")
  917. c.use_max_x = self.evaluate_input("Use Max X")
  918. c.use_max_y = self.evaluate_input("Use Max Y")
  919. c.use_max_z = self.evaluate_input("Use Max Z")
  920. #
  921. c.use_min_x = self.evaluate_input("Use Min X")
  922. c.use_min_y = self.evaluate_input("Use Min Y")
  923. c.use_min_z = self.evaluate_input("Use Min Z")
  924. c.use_transform_limit = self.evaluate_input("Affect Transform")
  925. c.owner_space = self.evaluate_input("Owner Space")
  926. c.influence = self.evaluate_input("Influence")
  927. print ("Creating Limit Location Constraint for bone: \""+ self.GetxForm().bGetObject().name + "\"")
  928. if self.parameters["Mute"]:
  929. c.enabled = False
  930. def __repr__(self):
  931. return self.signature.__repr__()
  932. def fill_parameters(self, node_prototype):
  933. fill_parameters(self, node_prototype)
  934. class LinkLimitRotation:
  935. def __init__(self, signature, base_tree):
  936. self.base_tree=base_tree
  937. self.signature = signature
  938. self.inputs = {
  939. "Input Relationship" : NodeSocket(is_input = True, to_socket = "Input Relationship", to_node = self,),
  940. "Use X" : NodeSocket(is_input = True, to_socket = "Use X", to_node = self,),
  941. "Use Y" : NodeSocket(is_input = True, to_socket = "Use Y", to_node = self,),
  942. "Use Z" : NodeSocket(is_input = True, to_socket = "Use Z", to_node = self,),
  943. "Max X" : NodeSocket(is_input = True, to_socket = "Max X", to_node = self,),
  944. "Max Y" : NodeSocket(is_input = True, to_socket = "Max Y", to_node = self,),
  945. "Max Z" : NodeSocket(is_input = True, to_socket = "Max Z", to_node = self,),
  946. "Min X" : NodeSocket(is_input = True, to_socket = "Min X", to_node = self,),
  947. "Min Y" : NodeSocket(is_input = True, to_socket = "Min Y", to_node = self,),
  948. "Min Z" : NodeSocket(is_input = True, to_socket = "Min Z", to_node = self,),
  949. "Affect Transform" : NodeSocket(is_input = True, to_socket = "Affect Transform", to_node = self,),
  950. "Owner Space" : NodeSocket(is_input = True, to_socket = "Owner Space", to_node = self,),
  951. "Influence" : NodeSocket(is_input = True, to_socket = "Influence", to_node = self,), }
  952. self.outputs = {
  953. "Output Relationship" : NodeSocket(from_socket = "Output Relationship", from_node=self) }
  954. self.parameters = {
  955. "Input Relationship":None,
  956. "Use X":None,
  957. "Use Y":None,
  958. "Use Z":None,
  959. "Max X":None,
  960. "Max Y":None,
  961. "Max Z":None,
  962. "Min X":None,
  963. "Min Y":None,
  964. "Min Z":None,
  965. "Affect Transform":None,
  966. "Owner Space":None,
  967. "Influence":None,
  968. "Mute":None,}
  969. # now set up the traverse target...
  970. self.inputs["Input Relationship"].set_traverse_target(self.outputs["Output Relationship"])
  971. self.outputs["Output Relationship"].set_traverse_target(self.inputs["Input Relationship"])
  972. self.node_type = 'LINK'
  973. def evaluate_input(self, input_name):
  974. return evaluate_input(self, input_name)
  975. def GetxForm(self):
  976. trace = trace_single_line_up(self, "Output Relationship")
  977. for node in trace[0]:
  978. if (node.__class__ in [xFormRoot, xFormArmature, xFormBone]):
  979. return node
  980. return None
  981. def bExecute(self, context):
  982. c = self.GetxForm().bGetObject().constraints.new('LIMIT_ROTATION')
  983. #
  984. c.max_x = self.evaluate_input("Max X")
  985. c.max_y = self.evaluate_input("Max Y")
  986. c.max_z = self.evaluate_input("Max Z")
  987. #
  988. c.min_x = self.evaluate_input("Min X")
  989. c.min_y = self.evaluate_input("Min Y")
  990. c.min_z = self.evaluate_input("Min Z")
  991. #
  992. c.use_limit_x = self.evaluate_input("Use X")
  993. c.use_limit_y = self.evaluate_input("Use Y")
  994. c.use_limit_z = self.evaluate_input("Use Z")
  995. #
  996. c.use_transform_limit = self.evaluate_input("Affect Transform")
  997. #
  998. c.owner_space = self.evaluate_input("Owner Space")
  999. c.influence = self.evaluate_input("Influence")
  1000. print ("Creating Limit Rotation Constraint for bone: \""+ self.GetxForm().bGetObject().name + "\"")
  1001. if self.parameters["Mute"]:
  1002. c.enabled = False
  1003. def __repr__(self):
  1004. return self.signature.__repr__()
  1005. def fill_parameters(self, node_prototype):
  1006. fill_parameters(self, node_prototype)
  1007. class LinkLimitScale:
  1008. def __init__(self, signature, base_tree):
  1009. self.base_tree=base_tree
  1010. self.signature = signature
  1011. self.inputs = {
  1012. "Input Relationship" : NodeSocket(is_input = True, to_socket = "Input Relationship", to_node = self,),
  1013. "Use Max X" : NodeSocket(is_input = True, to_socket = "Use Max X", to_node = self,),
  1014. "Max X" : NodeSocket(is_input = True, to_socket = "Max X", to_node = self,),
  1015. "Use Max Y" : NodeSocket(is_input = True, to_socket = "Use Max Y", to_node = self,),
  1016. "Max Y" : NodeSocket(is_input = True, to_socket = "Max Y", to_node = self,),
  1017. "Use Max Z" : NodeSocket(is_input = True, to_socket = "Use Max Z", to_node = self,),
  1018. "Max Z" : NodeSocket(is_input = True, to_socket = "Max Z", to_node = self,),
  1019. "Use Min X" : NodeSocket(is_input = True, to_socket = "Use Min X", to_node = self,),
  1020. "Min X" : NodeSocket(is_input = True, to_socket = "Min X", to_node = self,),
  1021. "Use Min Y" : NodeSocket(is_input = True, to_socket = "Use Min Y", to_node = self,),
  1022. "Min Y" : NodeSocket(is_input = True, to_socket = "Min Y", to_node = self,),
  1023. "Use Min Z" : NodeSocket(is_input = True, to_socket = "Use Min Z", to_node = self,),
  1024. "Min Z" : NodeSocket(is_input = True, to_socket = "Min Z", to_node = self,),
  1025. "Affect Transform" : NodeSocket(is_input = True, to_socket = "Affect Transform", to_node = self,),
  1026. "Owner Space" : NodeSocket(is_input = True, to_socket = "Owner Space", to_node = self,),
  1027. "Influence" : NodeSocket(is_input = True, to_socket = "Influence", to_node = self,), }
  1028. self.outputs = {
  1029. "Output Relationship" : NodeSocket(from_socket = "Output Relationship", from_node=self) }
  1030. self.parameters = {
  1031. "Input Relationship":None,
  1032. "Use Max X":None,
  1033. "Max X":None,
  1034. "Use Max Y":None,
  1035. "Max Y":None,
  1036. "Use Max Z":None,
  1037. "Max Z":None,
  1038. "Use Min X":None,
  1039. "Min X":None,
  1040. "Use Min Y":None,
  1041. "Min Y":None,
  1042. "Use Min Z":None,
  1043. "Min Z":None,
  1044. "Affect Transform":None,
  1045. "Owner Space":None,
  1046. "Influence":None,
  1047. "Mute":None,}
  1048. # now set up the traverse target...
  1049. self.inputs["Input Relationship"].set_traverse_target(self.outputs["Output Relationship"])
  1050. self.outputs["Output Relationship"].set_traverse_target(self.inputs["Input Relationship"])
  1051. self.node_type = 'LINK'
  1052. def evaluate_input(self, input_name):
  1053. return evaluate_input(self, input_name)
  1054. def GetxForm(self):
  1055. trace = trace_single_line_up(self, "Output Relationship")
  1056. for node in trace[0]:
  1057. if (node.__class__ in [xFormRoot, xFormArmature, xFormBone]):
  1058. return node
  1059. return None
  1060. def bExecute(self, context):
  1061. c = self.GetxForm().bGetObject().constraints.new('LIMIT_SCALE')
  1062. #
  1063. c.max_x = self.evaluate_input("Max X")
  1064. c.max_y = self.evaluate_input("Max Y")
  1065. c.max_z = self.evaluate_input("Max Z")
  1066. #
  1067. c.min_x = self.evaluate_input("Min X")
  1068. c.min_y = self.evaluate_input("Min Y")
  1069. c.min_z = self.evaluate_input("Min Z")
  1070. c.use_max_x = self.evaluate_input("Use Max X")
  1071. c.use_max_y = self.evaluate_input("Use Max Y")
  1072. c.use_max_z = self.evaluate_input("Use Max Z")
  1073. #
  1074. c.use_min_x = self.evaluate_input("Use Min X")
  1075. c.use_min_y = self.evaluate_input("Use Min Y")
  1076. c.use_min_z = self.evaluate_input("Use Min Z")
  1077. c.use_transform_limit = self.evaluate_input("Affect Transform")
  1078. c.owner_space = self.evaluate_input("Owner Space")
  1079. c.influence = self.evaluate_input("Influence")
  1080. print ("Creating Limit Scale Constraint for bone: \""+ self.GetxForm().bGetObject().name + "\"")
  1081. if self.parameters["Mute"]:
  1082. c.enabled = False
  1083. def __repr__(self):
  1084. return self.signature.__repr__()
  1085. def fill_parameters(self, node_prototype):
  1086. fill_parameters(self, node_prototype)
  1087. class LinkLimitDistance:
  1088. def __init__(self, signature, base_tree):
  1089. self.base_tree=base_tree
  1090. self.signature = signature
  1091. self.inputs = {
  1092. "Input Relationship" : NodeSocket(is_input = True, to_socket = "Input Relationship", to_node = self,),
  1093. "Head/Tail" : NodeSocket(is_input = True, to_socket = "Head/Tail", to_node = self,),
  1094. "UseBBone" : NodeSocket(is_input = True, to_socket = "UseBBone", to_node = self,),
  1095. "Distance" : NodeSocket(is_input = True, to_socket = "Distance", to_node = self,),
  1096. "Clamp Region" : NodeSocket(is_input = True, to_socket = "Clamp Region", to_node = self,),
  1097. "Affect Transform" : NodeSocket(is_input = True, to_socket = "Affect Transform", to_node = self,),
  1098. "Owner Space" : NodeSocket(is_input = True, to_socket = "Owner Space", to_node = self,),
  1099. "Target Space" : NodeSocket(is_input = True, to_socket = "Target Space", to_node = self,),
  1100. "Influence" : NodeSocket(is_input = True, to_socket = "Influence", to_node = self,),
  1101. "Target" : NodeSocket(is_input = True, to_socket = "Target", to_node = self,), }
  1102. self.outputs = {
  1103. "Output Relationship" : NodeSocket(from_socket = "Output Relationship", from_node=self) }
  1104. self.parameters = {
  1105. "Input Relationship":None,
  1106. "Head/Tail":None,
  1107. "UseBBone":None,
  1108. "Distance":None,
  1109. "Clamp Region":None,
  1110. "Affect Transform":None,
  1111. "Owner Space":None,
  1112. "Target Space":None,
  1113. "Influence":None,
  1114. "Target":None,
  1115. "Mute":None,}
  1116. # now set up the traverse target...
  1117. self.inputs["Input Relationship"].set_traverse_target(self.outputs["Output Relationship"])
  1118. self.outputs["Output Relationship"].set_traverse_target(self.inputs["Input Relationship"])
  1119. self.node_type = 'LINK'
  1120. def evaluate_input(self, input_name):
  1121. if (input_name == 'Target'):
  1122. socket = self.inputs.get(input_name)
  1123. return socket.from_node
  1124. else:
  1125. return evaluate_input(self, input_name)
  1126. def GetxForm(self):
  1127. trace = trace_single_line_up(self, "Output Relationship")
  1128. for node in trace[0]:
  1129. if (node.__class__ in [xFormRoot, xFormArmature, xFormBone]):
  1130. return node
  1131. return None
  1132. def bExecute(self, context):
  1133. c = self.GetxForm().bGetObject().constraints.new('LIMIT_DISTANCE')
  1134. get_target_and_subtarget(self, c)
  1135. #
  1136. c.distance = self.evaluate_input("Distance")
  1137. c.head_tail = self.evaluate_input("Head/Tail")
  1138. c.limit_mode = self.evaluate_input("Clamp Region")
  1139. c.use_bbone_shape = self.evaluate_input("UseBBone")
  1140. c.use_transform_limit = self.evaluate_input("Affect Transform")
  1141. c.owner_space = self.evaluate_input("Owner Space")
  1142. c.target_space = self.evaluate_input("Target Space")
  1143. c.influence = self.evaluate_input("Influence")
  1144. print ("Creating Limit Distance Constraint for bone: \""+ self.GetxForm().bGetObject().name + "\"")
  1145. if self.parameters["Mute"]:
  1146. c.enabled = False
  1147. def __repr__(self):
  1148. return self.signature.__repr__()
  1149. def fill_parameters(self, node_prototype):
  1150. fill_parameters(self, node_prototype)
  1151. # Tracking
  1152. class LinkStretchTo:
  1153. def __init__(self, signature, base_tree):
  1154. self.base_tree=base_tree
  1155. self.signature = signature
  1156. self.inputs = {
  1157. "Input Relationship" : NodeSocket(is_input = True, to_socket = "Input Relationship", to_node = self,),
  1158. "Head/Tail" : NodeSocket(is_input = True, to_socket = "Head/Tail", to_node = self,),
  1159. "UseBBone" : NodeSocket(is_input = True, to_socket = "UseBBone", to_node = self,),
  1160. "Original Length" : NodeSocket(is_input = True, to_socket = "Original Length", to_node = self,),
  1161. "Volume Variation" : NodeSocket(is_input = True, to_socket = "Volume Variation", to_node = self,),
  1162. "Use Volume Min" : NodeSocket(is_input = True, to_socket = "Use Volume Min", to_node = self,),
  1163. "Volume Min" : NodeSocket(is_input = True, to_socket = "Volume Min", to_node = self,),
  1164. "Use Volume Max" : NodeSocket(is_input = True, to_socket = "Use Volume Max", to_node = self,),
  1165. "Volume Max" : NodeSocket(is_input = True, to_socket = "Volume Max", to_node = self,),
  1166. "Smooth" : NodeSocket(is_input = True, to_socket = "Smooth", to_node = self,),
  1167. "Maintain Volume" : NodeSocket(is_input = True, to_socket = "Maintain Volume", to_node = self,),
  1168. "Rotation" : NodeSocket(is_input = True, to_socket = "Rotation", to_node = self,),
  1169. "Influence" : NodeSocket(is_input = True, to_socket = "Influence", to_node = self,),
  1170. "Target" : NodeSocket(is_input = True, to_socket = "Target", to_node = self,), }
  1171. self.outputs = {
  1172. "Output Relationship" : NodeSocket(from_socket = "Output Relationship", from_node=self) }
  1173. self.parameters = {
  1174. "Input Relationship":None,
  1175. "Head/Tail":None,
  1176. "UseBBone":None,
  1177. "Original Length":None,
  1178. "Volume Variation":None,
  1179. "Use Volume Min":None,
  1180. "Volume Min":None,
  1181. "Use Volume Max":None,
  1182. "Volume Max":None,
  1183. "Smooth":None,
  1184. "Maintain Volume":None,
  1185. "Rotation":None,
  1186. "Influence":None,
  1187. "Target":None,
  1188. "Mute":None,}
  1189. # now set up the traverse target...
  1190. self.inputs["Input Relationship"].set_traverse_target(self.outputs["Output Relationship"])
  1191. self.outputs["Output Relationship"].set_traverse_target(self.inputs["Input Relationship"])
  1192. self.node_type = 'LINK'
  1193. def evaluate_input(self, input_name):
  1194. if (input_name == 'Target'):
  1195. socket = self.inputs.get(input_name)
  1196. return socket.from_node
  1197. else:
  1198. return evaluate_input(self, input_name)
  1199. def GetxForm(self):
  1200. trace = trace_single_line_up(self, "Output Relationship")
  1201. for node in trace[0]:
  1202. if (node.__class__ in [xFormRoot, xFormArmature, xFormBone]):
  1203. return node
  1204. return None
  1205. def bExecute(self, context):
  1206. c = self.GetxForm().bGetObject().constraints.new('STRETCH_TO')
  1207. get_target_and_subtarget(self, c)
  1208. c.head_tail = self.evaluate_input("Head/Tail")
  1209. c.use_bbone_shape = self.evaluate_input("UseBBone")
  1210. c.bulge = self.evaluate_input("Volume Variation")
  1211. c.use_bulge_min = self.evaluate_input("Use Volume Min")
  1212. c.bulge_min = self.evaluate_input("Volume Min")
  1213. c.use_bulge_max = self.evaluate_input("Use Volume Max")
  1214. c.bulge_max = self.evaluate_input("Volume Max")
  1215. c.bulge_smooth = self.evaluate_input("Smooth")
  1216. c.keep_axis = self.evaluate_input("Rotation")
  1217. c.volume = self.evaluate_input("Maintain Volume")
  1218. c.rest_length = self.evaluate_input("Original Length")
  1219. c.influence = self.evaluate_input("Influence")
  1220. if (c.rest_length == 0):
  1221. # this is meant to be set automatically.
  1222. c.rest_length = self.GetxForm().bGetObject().bone.length
  1223. print ("Creating Stretch-To Constraint for bone: \""+ self.GetxForm().bGetObject().name + "\"")
  1224. if self.parameters["Mute"]:
  1225. c.enabled = False
  1226. def __repr__(self):
  1227. return self.signature.__repr__()
  1228. def fill_parameters(self, node_prototype):
  1229. fill_parameters(self, node_prototype)
  1230. class LinkDampedTrack:
  1231. def __init__(self, signature, base_tree):
  1232. self.base_tree=base_tree
  1233. self.signature = signature
  1234. self.inputs = {
  1235. "Input Relationship" : NodeSocket(is_input = True, to_socket = "Input Relationship", to_node = self,),
  1236. "Head/Tail" : NodeSocket(is_input = True, to_socket = "Head/Tail", to_node = self,),
  1237. "UseBBone" : NodeSocket(is_input = True, to_socket = "UseBBone", to_node = self,),
  1238. "Track Axis" : NodeSocket(is_input = True, to_socket = "Track Axis", to_node = self,),
  1239. "Influence" : NodeSocket(is_input = True, to_socket = "Influence", to_node = self,),
  1240. "Target" : NodeSocket(is_input = True, to_socket = "Target", to_node = self,), }
  1241. self.outputs = {
  1242. "Output Relationship" : NodeSocket(from_socket = "Output Relationship", from_node=self) }
  1243. self.parameters = {
  1244. "Input Relationship":None,
  1245. "Head/Tail":None,
  1246. "UseBBone":None,
  1247. "Track Axis":None,
  1248. "Influence":None,
  1249. "Target":None,
  1250. "Mute":None,}
  1251. # now set up the traverse target...
  1252. self.inputs["Input Relationship"].set_traverse_target(self.outputs["Output Relationship"])
  1253. self.outputs["Output Relationship"].set_traverse_target(self.inputs["Input Relationship"])
  1254. self.node_type = 'LINK'
  1255. def evaluate_input(self, input_name):
  1256. if (input_name == 'Target'):
  1257. socket = self.inputs.get(input_name)
  1258. return socket.from_node
  1259. else:
  1260. return evaluate_input(self, input_name)
  1261. def GetxForm(self):
  1262. trace = trace_single_line_up(self, "Output Relationship")
  1263. for node in trace[0]:
  1264. if (node.__class__ in [xFormRoot, xFormArmature, xFormBone]):
  1265. return node
  1266. return None
  1267. def bExecute(self, context):
  1268. c = self.GetxForm().bGetObject().constraints.new('DAMPED_TRACK')
  1269. get_target_and_subtarget(self, c)
  1270. c.head_tail = self.evaluate_input("Head/Tail")
  1271. c.use_bbone_shape = self.evaluate_input("UseBBone")
  1272. c.track_axis = self.evaluate_input("Track Axis")
  1273. c.influence = self.evaluate_input("Influence")
  1274. print ("Creating Damped-Track Constraint for bone: \""+ self.GetxForm().bGetObject().name + "\"")
  1275. if self.parameters["Mute"]:
  1276. c.enabled = False
  1277. def __repr__(self):
  1278. return self.signature.__repr__()
  1279. def fill_parameters(self, node_prototype):
  1280. fill_parameters(self, node_prototype)
  1281. class LinkLockedTrack:
  1282. def __init__(self, signature, base_tree):
  1283. self.base_tree=base_tree
  1284. self.signature = signature
  1285. self.inputs = {
  1286. "Input Relationship" : NodeSocket(is_input = True, to_socket = "Input Relationship", to_node = self,),
  1287. "Head/Tail" : NodeSocket(is_input = True, to_socket = "Head/Tail", to_node = self,),
  1288. "UseBBone" : NodeSocket(is_input = True, to_socket = "UseBBone", to_node = self,),
  1289. "Track Axis" : NodeSocket(is_input = True, to_socket = "Track Axis", to_node = self,),
  1290. "Lock Axis" : NodeSocket(is_input = True, to_socket = "Lock Axis", to_node = self,),
  1291. "Influence" : NodeSocket(is_input = True, to_socket = "Influence", to_node = self,),
  1292. "Target" : NodeSocket(is_input = True, to_socket = "Target", to_node = self,), }
  1293. self.outputs = {
  1294. "Output Relationship" : NodeSocket(from_socket = "Output Relationship", from_node=self) }
  1295. self.parameters = {
  1296. "Input Relationship":None,
  1297. "Head/Tail":None,
  1298. "UseBBone":None,
  1299. "Track Axis":None,
  1300. "Lock Axis":None,
  1301. "Influence":None,
  1302. "Target":None,
  1303. "Mute":None,}
  1304. # now set up the traverse target...
  1305. self.inputs["Input Relationship"].set_traverse_target(self.outputs["Output Relationship"])
  1306. self.outputs["Output Relationship"].set_traverse_target(self.inputs["Input Relationship"])
  1307. self.node_type = 'LINK'
  1308. def evaluate_input(self, input_name):
  1309. if (input_name == 'Target'):
  1310. socket = self.inputs.get(input_name)
  1311. return socket.from_node
  1312. else:
  1313. return evaluate_input(self, input_name)
  1314. def GetxForm(self):
  1315. trace = trace_single_line_up(self, "Output Relationship")
  1316. for node in trace[0]:
  1317. if (node.__class__ in [xFormRoot, xFormArmature, xFormBone]):
  1318. return node
  1319. return None
  1320. def bExecute(self, context):
  1321. c = self.GetxForm().bGetObject().constraints.new('LOCKED_TRACK')
  1322. get_target_and_subtarget(self, c)
  1323. c.head_tail = self.evaluate_input("Head/Tail")
  1324. c.use_bbone_shape = self.evaluate_input("UseBBone")
  1325. c.track_axis = self.evaluate_input("Track Axis")
  1326. c.lock_axis = self.evaluate_input("Lock Axis")
  1327. c.influence = self.evaluate_input("Influence")
  1328. print ("Creating Locked-Track Constraint for bone: \""+ self.GetxForm().bGetObject().name + "\"")
  1329. if self.parameters["Mute"]:
  1330. c.enabled = False
  1331. def __repr__(self):
  1332. return self.signature.__repr__()
  1333. def fill_parameters(self, node_prototype):
  1334. fill_parameters(self, node_prototype)
  1335. class LinkTrackTo:
  1336. def __init__(self, signature, base_tree):
  1337. self.base_tree=base_tree
  1338. self.signature = signature
  1339. self.inputs = {
  1340. "Input Relationship" : NodeSocket(is_input = True, to_socket = "Input Relationship", to_node = self,),
  1341. "Head/Tail" : NodeSocket(is_input = True, to_socket = "Head/Tail", to_node = self,),
  1342. "UseBBone" : NodeSocket(is_input = True, to_socket = "UseBBone", to_node = self,),
  1343. "Track Axis" : NodeSocket(is_input = True, to_socket = "Track Axis", to_node = self,),
  1344. "Up Axis" : NodeSocket(is_input = True, to_socket = "Up Axis", to_node = self,),
  1345. "Use Target Z" : NodeSocket(is_input = True, to_socket = "Use Target Z", to_node = self,),
  1346. "Influence" : NodeSocket(is_input = True, to_socket = "Influence", to_node = self,),
  1347. "Target" : NodeSocket(is_input = True, to_socket = "Target", to_node = self,), }
  1348. self.outputs = {
  1349. "Output Relationship" : NodeSocket(from_socket = "Output Relationship", from_node=self) }
  1350. self.parameters = {
  1351. "Input Relationship":None,
  1352. "Head/Tail":None,
  1353. "UseBBone":None,
  1354. "Track Axis":None,
  1355. "Up Axis":None,
  1356. "Use Target Z":None,
  1357. "Influence":None,
  1358. "Target":None,
  1359. "Mute":None,}
  1360. # now set up the traverse target...
  1361. self.inputs["Input Relationship"].set_traverse_target(self.outputs["Output Relationship"])
  1362. self.outputs["Output Relationship"].set_traverse_target(self.inputs["Input Relationship"])
  1363. self.node_type = 'LINK'
  1364. def evaluate_input(self, input_name):
  1365. if (input_name == 'Target'):
  1366. socket = self.inputs.get(input_name)
  1367. return socket.from_node
  1368. else:
  1369. return evaluate_input(self, input_name)
  1370. def GetxForm(self):
  1371. trace = trace_single_line_up(self, "Output Relationship")
  1372. for node in trace[0]:
  1373. if (node.__class__ in [xFormRoot, xFormArmature, xFormBone]):
  1374. return node
  1375. return None
  1376. def bExecute(self, context):
  1377. c = self.GetxForm().bGetObject().constraints.new('TRACK_TO')
  1378. get_target_and_subtarget(self, c)
  1379. c.head_tail = self.evaluate_input("Head/Tail")
  1380. c.use_bbone_shape = self.evaluate_input("UseBBone")
  1381. c.track_axis = self.evaluate_input("Track Axis")
  1382. c.up_axis = self.evaluate_input("Up Axis")
  1383. c.use_target_z = self.evaluate_input("Use Target Z")
  1384. c.influence = self.evaluate_input("Influence")
  1385. print ("Creating Track-To Constraint for bone: \""+ self.GetxForm().bGetObject().name + "\"")
  1386. if self.parameters["Mute"]:
  1387. c.enabled = False
  1388. def __repr__(self):
  1389. return self.signature.__repr__()
  1390. def fill_parameters(self, node_prototype):
  1391. fill_parameters(self, node_prototype)
  1392. # relationships & misc.
  1393. class LinkInheritConstraint:
  1394. def __init__(self, signature, base_tree):
  1395. self.base_tree=base_tree
  1396. self.signature = signature
  1397. self.inputs = {
  1398. "Input Relationship" : NodeSocket(is_input = True, to_socket = "Input Relationship", to_node = self,),
  1399. "Location" : NodeSocket(is_input = True, to_socket = "Location", to_node = self,),
  1400. "Rotation" : NodeSocket(is_input = True, to_socket = "Rotation", to_node = self,),
  1401. "Scale" : NodeSocket(is_input = True, to_socket = "Scale", to_node = self,),
  1402. "Influence" : NodeSocket(is_input = True, to_socket = "Influence", to_node = self,),
  1403. "Target" : NodeSocket(is_input = True, to_socket = "Target", to_node = self,), }
  1404. self.outputs = {
  1405. "Output Relationship" : NodeSocket(from_socket = "Output Relationship", from_node=self) }
  1406. self.parameters = {
  1407. "Input Relationship":None,
  1408. "Location":None,
  1409. "Rotation":None,
  1410. "Scale":None,
  1411. "Influence":None,
  1412. "Target":None,
  1413. "Mute":None,}
  1414. # now set up the traverse target...
  1415. self.inputs["Input Relationship"].set_traverse_target(self.outputs["Output Relationship"])
  1416. self.outputs["Output Relationship"].set_traverse_target(self.inputs["Input Relationship"])
  1417. self.node_type = 'LINK'
  1418. def evaluate_input(self, input_name):
  1419. if (input_name == 'Target'):
  1420. socket = self.inputs.get(input_name)
  1421. return socket.from_node
  1422. else:
  1423. return evaluate_input(self, input_name)
  1424. def GetxForm(self):
  1425. trace = trace_single_line_up(self, "Output Relationship")
  1426. for node in trace[0]:
  1427. if (node.__class__ in [xFormRoot, xFormArmature, xFormBone]):
  1428. return node
  1429. return None
  1430. def bExecute(self, context):
  1431. c = self.GetxForm().bGetObject().constraints.new('CHILD_OF')
  1432. get_target_and_subtarget(self, c)
  1433. c.use_location_x = self.evaluate_input("Location")[0]
  1434. c.use_location_y = self.evaluate_input("Location")[1]
  1435. c.use_location_z = self.evaluate_input("Location")[2]
  1436. c.use_rotation_x = self.evaluate_input("Rotation")[0]
  1437. c.use_rotation_y = self.evaluate_input("Rotation")[1]
  1438. c.use_rotation_z = self.evaluate_input("Rotation")[2]
  1439. c.use_scale_x = self.evaluate_input("Scale")[0]
  1440. c.use_scale_y = self.evaluate_input("Scale")[1]
  1441. c.use_scale_z = self.evaluate_input("Scale")[2]
  1442. c.influence = self.evaluate_input("Influence")
  1443. c.set_inverse_pending
  1444. print ("Creating Child-of Constraint for bone: \""+ self.GetxForm().bGetObject().name + "\"")
  1445. if self.parameters["Mute"]:
  1446. c.enabled = False
  1447. def __repr__(self):
  1448. return self.signature.__repr__()
  1449. def fill_parameters(self, node_prototype):
  1450. fill_parameters(self, node_prototype)
  1451. # Inverse Kinematics:
  1452. #
  1453. # r = self.inputs.new('BooleanSocket', "Inherit Rotation")
  1454. # c = self.inputs.new('BooleanSocket', "Connected")
  1455. # s = self.inputs.new('EnumInheritScale', "Inherit Scale")
  1456. # self.inputs.new ('xFormSocket', "Target")
  1457. # self.inputs.new ('xFormSocket', "Pole Target")
  1458. # self.inputs.new ('IKChainLengthSocket', "Chain Length")
  1459. # self.inputs.new ('BooleanSocket', "Use Tail")
  1460. # self.inputs.new ('BooleanSocket', "Stretch")
  1461. # self.inputs.new ('FloatFactorSocket', "Position")
  1462. # self.inputs.new ('FloatFactorSocket', "Rotation")
  1463. # self.inputs.new ('FloatFactorSocket', "Influence")
  1464. # self.outputs.new('RelationshipSocket', "Inheritance")
  1465. # self.inputs.new('xFormSocket', "Parent")
  1466. #
  1467. # Ugghh, this one is a little weird
  1468. # I treat IK as a kind of inheritance
  1469. # that is mutually exclusive with other inheritance
  1470. # since Blender and other softwares treat it specially, anyway
  1471. # e.g. in Blender it's always treated as the last constraint
  1472. # While it may be annoying to have it always appear first in each bones'
  1473. # stack, because this does not affect behaviour, I do not really care.
  1474. class LinkInverseKinematics:
  1475. def __init__(self, signature, base_tree):
  1476. self.base_tree=base_tree
  1477. self.signature = signature
  1478. self.inputs = {
  1479. # Inheritance bits
  1480. "Input Relationship" : NodeSocket(is_input = True, to_socket = "Input Relationship", to_node = self,),
  1481. "Inherit Rotation" : NodeSocket(is_input = True, to_socket = "Inherit Rotation", to_node = self,),
  1482. "Inherit Scale" : NodeSocket(is_input = True, to_socket = "Inherit Scale", to_node = self,),
  1483. "Connected" : NodeSocket(is_input = True, to_socket = "Connected", to_node = self,),
  1484. # Constraint stuff
  1485. "Chain Length" : NodeSocket(is_input = True, to_socket = "Chain Length", to_node = self,),
  1486. "Use Tail" : NodeSocket(is_input = True, to_socket = "Use Tail", to_node = self,),
  1487. "Stretch" : NodeSocket(is_input = True, to_socket = "Stretch", to_node = self,),
  1488. "Position" : NodeSocket(is_input = True, to_socket = "Position", to_node = self,),
  1489. "Rotation" : NodeSocket(is_input = True, to_socket = "Rotation", to_node = self,),
  1490. "Influence" : NodeSocket(is_input = True, to_socket = "Influence", to_node = self,),
  1491. "Target" : NodeSocket(is_input = True, to_socket = "Target", to_node = self,),
  1492. "Pole Target" : NodeSocket(is_input = True, to_socket = "Pole Target", to_node = self,), }
  1493. self.outputs = {
  1494. "Output Relationship" : NodeSocket(from_socket = "Output Relationship", from_node=self) }
  1495. self.parameters = {
  1496. "Input Relationship":None,
  1497. "Inherit Rotation":None,
  1498. "Inherit Scale":None,
  1499. "Connected":None,
  1500. "Chain Length":None,
  1501. "Use Tail":None,
  1502. "Stretch":None,
  1503. "Position":None,
  1504. "Rotation":None,
  1505. "Influence":None,
  1506. "Target":None,
  1507. "Pole Target":None,
  1508. "Mute":None,}
  1509. # now set up the traverse target...
  1510. self.inputs["Input Relationship"].set_traverse_target(self.outputs["Output Relationship"])
  1511. self.outputs["Output Relationship"].set_traverse_target(self.inputs["Input Relationship"])
  1512. self.node_type = 'LINK'
  1513. def evaluate_input(self, input_name):
  1514. if (input_name == 'Target') or (input_name == 'Pole Target'):
  1515. socket = self.inputs.get(input_name)
  1516. return socket.from_node
  1517. else:
  1518. return evaluate_input(self, input_name)
  1519. def GetxForm(self):
  1520. trace = trace_single_line_up(self, "Output Relationship")
  1521. for node in trace[0]:
  1522. if (node.__class__ in [xFormRoot, xFormArmature, xFormBone]):
  1523. return node
  1524. return None
  1525. def bExecute(self, context):
  1526. # do not handle any inheritance stuff here, that is dealt with
  1527. # by the xForm nodes instead!
  1528. myOb = self.GetxForm().bGetObject()
  1529. c = self.GetxForm().bGetObject().constraints.new('IK')
  1530. get_target_and_subtarget(self, c)
  1531. get_target_and_subtarget(self, c, input_name = 'Pole Target')
  1532. if (c.pole_target): # Calculate the pole angle, the user shouldn't have to.
  1533. pole_object = c.pole_target
  1534. pole_location = pole_object.matrix_world.decompose()[0]
  1535. if (c.pole_subtarget):
  1536. pole_object = c.pole_target.pose.bones[c.subtarget]
  1537. pole_location = pole_object.matrix.decompose()[0]
  1538. #HACK HACK
  1539. handle_location = myOb.bone.tail_local if (self.evaluate_input("Use Tail")) else myOb.bone.head_local
  1540. counter = 0
  1541. parent = myOb
  1542. base_bone = myOb
  1543. while (parent is not None):
  1544. if ((self.evaluate_input("Chain Length") != 0) and (counter > self.evaluate_input("Chain Length"))):
  1545. break
  1546. base_bone = parent
  1547. parent = parent.parent
  1548. counter+=1
  1549. head_location = base_bone.bone.head_local
  1550. pole_normal = (handle_location - head_location).cross(pole_location - head_location)
  1551. vector_u = myOb.bone.x_axis
  1552. vector_v = pole_normal.cross(base_bone.bone.y_axis)
  1553. angle = vector_u.angle(vector_v)
  1554. if (vector_u.cross(vector_v).angle(base_bone.bone.y_axis) < 1):
  1555. angle = -angle
  1556. c.pole_angle = angle
  1557. c.chain_count = self.evaluate_input("Chain Length")
  1558. c.use_tail = self.evaluate_input("Use Tail")
  1559. c.use_stretch = self.evaluate_input("Stretch")
  1560. c.weight = self.evaluate_input("Position")
  1561. c.orient_weight = self.evaluate_input("Rotation")
  1562. c.influence = self.evaluate_input("Influence")
  1563. # this should be sufficient, I think use_location and use_rotation
  1564. # are meaningless if the weight is 0, anyway.
  1565. # Well, the minimum weight is 0.01, so we have to get the input again.
  1566. c.use_location = self.evaluate_input("Position") > 0
  1567. c.use_rotation = self.evaluate_input("Rotation") > 0
  1568. # this is a little annoying because the constraint can have a
  1569. # positive value for position/rotation without it being enabled.
  1570. print ("Creating IK Constraint for bone: \""+ self.GetxForm().bGetObject().name + "\"")
  1571. if self.parameters["Mute"]:
  1572. c.enabled = False
  1573. def __repr__(self):
  1574. return self.signature.__repr__()
  1575. def fill_parameters(self, node_prototype):
  1576. fill_parameters(self, node_prototype)
  1577. #*#-------------------------------#++#-------------------------------#*#
  1578. # G E N E R I C N O D E S
  1579. #*#-------------------------------#++#-------------------------------#*#
  1580. # in reality, none of these inputs have names
  1581. # so I am using the socket name for now
  1582. # I suppose I could use any name :3
  1583. class InputFloat:
  1584. '''A node representing float input'''
  1585. def __init__(self, signature, base_tree):
  1586. self.base_tree=base_tree
  1587. self.signature = signature
  1588. self.outputs = {"Float Input" : NodeSocket(from_socket = "Float Input", from_node=self) }
  1589. self.parameters = {"Float Input":None, "Mute":None}
  1590. self.node_type = 'UTILITY'
  1591. def evaluate_input(self, input_name):
  1592. return self.parameters["Float Input"]
  1593. def bExecute(self, bContext = None,):
  1594. pass
  1595. def __repr__(self):
  1596. return self.signature.__repr__()
  1597. def fill_parameters(self, node_prototype):
  1598. fill_parameters(self, node_prototype)
  1599. class InputVector:
  1600. '''A node representing vector input'''
  1601. def __init__(self, signature, base_tree):
  1602. self.base_tree=base_tree
  1603. self.signature = signature
  1604. self.outputs = {"VectorSocket" : NodeSocket(from_socket = 'VectorSocket', from_node=self) }
  1605. self.parameters = {'VectorSocket':None, "Mute":None}
  1606. self.node_type = 'UTILITY'
  1607. def evaluate_input(self, input_name):
  1608. return self.parameters["VectorSocket"]
  1609. def bExecute(self, bContext = None,):
  1610. pass
  1611. def __repr__(self):
  1612. return self.signature.__repr__()
  1613. def fill_parameters(self, node_prototype):
  1614. fill_parameters(self, node_prototype)
  1615. class InputBoolean:
  1616. '''A node representing boolean input'''
  1617. def __init__(self, signature, base_tree):
  1618. self.base_tree=base_tree
  1619. self.signature = signature
  1620. self.outputs = {"BooleanSocket" : NodeSocket(from_socket = 'BooleanSocket', from_node=self) }
  1621. self.parameters = {'BooleanSocket':None, "Mute":None}
  1622. self.node_type = 'UTILITY'
  1623. def evaluate_input(self, input_name):
  1624. return self.parameters["BooleanSocket"]
  1625. def bExecute(self, bContext = None,):
  1626. pass
  1627. def __repr__(self):
  1628. return self.signature.__repr__()
  1629. def fill_parameters(self, node_prototype):
  1630. fill_parameters(self, node_prototype)
  1631. class InputBooleanThreeTuple:
  1632. '''A node representing inheritance'''
  1633. def __init__(self, signature, base_tree):
  1634. self.base_tree=base_tree
  1635. self.signature = signature
  1636. self.outputs = {"BooleanThreeTupleSocket" : NodeSocket(from_socket = 'BooleanThreeTupleSocket', from_node=self) }
  1637. self.parameters = {'BooleanThreeTupleSocket':None, "Mute":None}
  1638. self.node_type = 'UTILITY'
  1639. def evaluate_input(self, input_name):
  1640. return self.parameters["BooleanThreeTupleSocket"]
  1641. def bExecute(self, bContext = None,):
  1642. pass
  1643. def __repr__(self):
  1644. return self.signature.__repr__()
  1645. def fill_parameters(self, node_prototype):
  1646. fill_parameters(self, node_prototype)
  1647. class InputRotationOrder:
  1648. '''A node representing string input for rotation order'''
  1649. def __init__(self, signature, base_tree):
  1650. self.base_tree=base_tree
  1651. self.signature = signature
  1652. self.outputs = {"RotationOrderSocket" : NodeSocket(from_socket = 'RotationOrderSocket', from_node=self) }
  1653. self.parameters = {'RotationOrderSocket':None, "Mute":None}
  1654. self.node_type = 'UTILITY'
  1655. def evaluate_input(self, input_name):
  1656. return self.parameters["RotationOrderSocket"]
  1657. def bExecute(self, bContext = None,):
  1658. pass
  1659. def __repr__(self):
  1660. return self.signature.__repr__()
  1661. def fill_parameters(self, node_prototype):
  1662. fill_parameters(self, node_prototype)
  1663. class InputTransformSpace:
  1664. '''A node representing string input for transform space'''
  1665. def __init__(self, signature, base_tree):
  1666. self.base_tree=base_tree
  1667. self.signature = signature
  1668. self.outputs = {"TransformSpaceSocket" : NodeSocket(from_socket = 'TransformSpaceSocket', from_node=self) }
  1669. self.parameters = {'TransformSpaceSocket':None, "Mute":None}
  1670. self.node_type = 'UTILITY'
  1671. def evaluate_input(self, input_name):
  1672. return self.parameters["TransformSpaceSocket"]
  1673. def bExecute(self, bContext = None,):
  1674. pass
  1675. def __repr__(self):
  1676. return self.signature.__repr__()
  1677. def fill_parameters(self, node_prototype):
  1678. fill_parameters(self, node_prototype)
  1679. class InputString:
  1680. '''A node representing string input'''
  1681. def __init__(self, signature, base_tree):
  1682. self.base_tree=base_tree
  1683. self.signature = signature
  1684. self.outputs = {"StringSocket" : NodeSocket(from_socket = 'StringSocket', from_node=self) }
  1685. self.parameters = {'StringSocket':None, "Mute":None}
  1686. self.node_type = 'UTILITY'
  1687. def evaluate_input(self, input_name):
  1688. return self.parameters["StringSocket"]
  1689. def bExecute(self, bContext = None,):
  1690. pass
  1691. def __repr__(self):
  1692. return self.signature.__repr__()
  1693. def fill_parameters(self, node_prototype):
  1694. fill_parameters(self, node_prototype)
  1695. class InputQuaternion:
  1696. '''A node representing quaternion input'''
  1697. def __init__(self, signature, base_tree):
  1698. self.base_tree=base_tree
  1699. self.signature = signature
  1700. self.outputs = {"QuaternionSocket" : NodeSocket(from_socket = 'QuaternionSocket', from_node=self) }
  1701. self.parameters = {'QuaternionSocket':None, "Mute":None}
  1702. self.node_type = 'UTILITY'
  1703. def evaluate_input(self, input_name):
  1704. return self.parameters["QuaternionSocket"]
  1705. def bExecute(self, bContext = None,):
  1706. pass
  1707. def __repr__(self):
  1708. return self.signature.__repr__()
  1709. def fill_parameters(self, node_prototype):
  1710. fill_parameters(self, node_prototype)
  1711. class InputQuaternionAA:
  1712. '''A node representing axis-angle quaternion input'''
  1713. def __init__(self, signature, base_tree):
  1714. self.base_tree=base_tree
  1715. self.signature = signature
  1716. self.outputs = {"QuaternionSocketAA" : NodeSocket(from_socket = 'QuaternionSocketAA', from_node=self) }
  1717. self.parameters = {'QuaternionSocketAA':None, "Mute":None}
  1718. self.node_type = 'UTILITY'
  1719. def evaluate_input(self, input_name):
  1720. return self.parameters["QuaternionSocketAA"]
  1721. def bExecute(self, bContext = None,):
  1722. pass
  1723. def __repr__(self):
  1724. return self.signature.__repr__()
  1725. def fill_parameters(self, node_prototype):
  1726. fill_parameters(self, node_prototype)
  1727. class InputMatrix:
  1728. '''A node representing axis-angle quaternion input'''
  1729. def __init__(self, signature, base_tree):
  1730. self.base_tree=base_tree
  1731. self.signature = signature
  1732. self.outputs = {"Matrix" : NodeSocket(from_socket = 'Matrix', from_node=self) }
  1733. self.parameters = {'Matrix':None, "Mute":None}
  1734. self.node_type = 'UTILITY'
  1735. def evaluate_input(self, input_name):
  1736. return self.parameters["Matrix"]
  1737. def bExecute(self, bContext = None,):
  1738. pass
  1739. def __repr__(self):
  1740. return self.signature.__repr__()
  1741. def fill_parameters(self, node_prototype):
  1742. # this node is peculiar for how its data is input
  1743. # It uses node properties that are not addressable as sockets.
  1744. from mathutils import Matrix
  1745. matrix = ( node_prototype.first_row[ 0], node_prototype.first_row[ 1], node_prototype.first_row[ 2], node_prototype.first_row[ 3],
  1746. node_prototype.second_row[0], node_prototype.second_row[1], node_prototype.second_row[2], node_prototype.second_row[3],
  1747. node_prototype.third_row[ 0], node_prototype.third_row[ 1], node_prototype.third_row[ 2], node_prototype.third_row[ 3],
  1748. node_prototype.fourth_row[0], node_prototype.fourth_row[1], node_prototype.fourth_row[2], node_prototype.fourth_row[3], )
  1749. self.parameters["Matrix"] = Matrix([matrix[0:4], matrix[4:8], matrix[8:12], matrix[12:16]])
  1750. print (self.parameters["Matrix"])
  1751. # # NOT YET IMPLEMENTED:
  1752. # class InputMatrixNode(Node, MantisNode):
  1753. # '''A node representing matrix input'''
  1754. # inputs =
  1755. # # the node is implemented as a set of sixteen float inputs
  1756. # # but I think I can boil it down to one matrix input
  1757. # class ScaleBoneLengthNode(Node, MantisNode):
  1758. # '''Scale Bone Length'''
  1759. # pass