deformer_containers.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. from .node_container_common import *
  2. from .xForm_containers import xFormGeometryObject
  3. from bpy.types import Node
  4. from .base_definitions import MantisNode
  5. def TellClasses():
  6. return [
  7. DeformerArmature,
  8. ]
  9. def default_evaluate_input(nc, input_name):
  10. # duped from link_containers... should be common?
  11. # should catch 'Target', 'Pole Target' and ArmatureConstraint targets, too
  12. if ('Target' in input_name) and input_name != "Target Space":
  13. socket = nc.inputs.get(input_name)
  14. if socket.is_linked:
  15. return socket.links[0].from_node
  16. return None
  17. else:
  18. return evaluate_input(nc, input_name)
  19. # semi-duplicated from link_containers
  20. def GetxForm(nc):
  21. trace = trace_single_line_up(nc, "Deformer")
  22. for node in trace[0]:
  23. if (node.__class__ in [xFormGeometryObject]):
  24. return node
  25. raise GraphError("%s is not connected to a downstream xForm" % nc)
  26. class DeformerArmature:
  27. '''A node representing an armature deformer'''
  28. def __init__(self, signature, base_tree):
  29. self.base_tree=base_tree
  30. self.signature = signature
  31. self.inputs = {
  32. "Input Relationship" : NodeSocket(is_input = True, name = "Input Relationship", node = self,),
  33. "Target" : NodeSocket(is_input = True, name = "Target", node = self,),
  34. "Vertex Group" : NodeSocket(is_input = True, name = "Vertex Group", node = self),
  35. "Preserve Volume" : NodeSocket(is_input = True, name = "Preserve Volume", node = self),
  36. "Use Multi Modifier" : NodeSocket(is_input = True, name = "Use Multi Modifier", node = self),
  37. "Use Envelopes" : NodeSocket(is_input = True, name = "Use Envelopes", node = self),
  38. "Use Vertex Groups" : NodeSocket(is_input = True, name = "Use Vertex Groups", node = self),
  39. "Skinning Method" : NodeSocket(is_input = True, name = "Skinning Method", node = self),
  40. }
  41. self.outputs = {
  42. "Deformer" : NodeSocket(is_input = False, name = "Deformer", node=self), }
  43. self.parameters = {
  44. "Name" : None,
  45. "Target" : None,
  46. "Vertex Group" : None,
  47. "Preserve Volume" : None,
  48. "Use Multi Modifier" : None,
  49. "Use Envelopes" : None,
  50. "Use Vertex Groups" : None,
  51. "Skinning Method" : None,
  52. }
  53. # now set up the traverse target...
  54. self.inputs["Input Relationship"].set_traverse_target(self.outputs["Deformer"])
  55. self.outputs["Deformer"].set_traverse_target(self.inputs["Input Relationship"])
  56. self.node_type = "LINK"
  57. def evaluate_input(self, input_name):
  58. return default_evaluate_input(self, input_name)
  59. def GetxForm(self):
  60. return GetxForm(self)
  61. def bExecute(self, bContext = None,):
  62. prGreen("Executing Armature Deform Node\n")
  63. print(self.GetxForm())
  64. prOrange("My object: %s\n" % (self.GetxForm().bGetObject()))
  65. prepare_parameters(self)
  66. d = self.GetxForm().bGetObject().modifiers.new(self.evaluate_input("Name"), type='ARMATURE')
  67. self.bObject = d
  68. get_target_and_subtarget(self, d)
  69. props_sockets = {
  70. 'vertex_group' : ("Vertex Group", ""),
  71. 'use_deform_preserve_volume' : ("Preserve Volume", False),
  72. 'use_multi_modifier' : ("Use Multi Modifier", False),
  73. 'use_bone_envelopes' : ("Use Envelopes", False),
  74. 'use_vertex_groups' : ("Use Vertex Groups", False),
  75. }
  76. evaluate_sockets(self, d, props_sockets)
  77. def initialize_vgroups(self, use_existing = False):
  78. ob = self.GetxForm().bGetObject()
  79. if use_existing == False:
  80. ob.vertex_groups.clear()
  81. armOb = self.evaluate_input("Target").bGetObject()
  82. deform_bones = []
  83. for b in armOb.data.bones:
  84. if b.use_deform == True:
  85. deform_bones.append(b)
  86. for b in deform_bones:
  87. vg = ob.vertex_groups.get(b.name)
  88. if not vg:
  89. vg = ob.vertex_groups.new(name=b.name)
  90. num_verts = len(ob.data.vertices)
  91. vg.add(range(num_verts), 0, 'REPLACE')
  92. def bFinalize(self, bContext=None):
  93. if (skin_method := self.evaluate_input("Skinning Method")) == "AUTOMATIC_HEAT":
  94. # This is reatarded and leads to somewhat unpredictable
  95. # behaviour, e.g. what object will be selected? What mode?
  96. # also bpy.ops is ugly and prone to error when used in
  97. # scripts. I don't intend to use bpy.ops when I can avoid it.
  98. import bpy
  99. self.initialize_vgroups()
  100. bContext.view_layer.depsgraph.update()
  101. ob = self.GetxForm().bGetObject()
  102. armOb = self.evaluate_input("Target").bGetObject()
  103. deform_bones = []
  104. for pb in armOb.pose.bones:
  105. if pb.bone.use_deform == True:
  106. deform_bones.append(pb)
  107. context_override = {
  108. 'active_object':ob,
  109. 'selected_objects':[ob, armOb],
  110. 'active_pose_bone':deform_bones[0],
  111. 'selected_pose_bones':deform_bones,}
  112. #
  113. with bContext.temp_override(**{'active_object':armOb}):
  114. bpy.ops.object.mode_set(mode='POSE')
  115. bpy.ops.pose.select_all(action='SELECT')
  116. with bContext.temp_override(**context_override):
  117. bpy.ops.paint.weight_paint_toggle()
  118. bpy.ops.paint.weight_from_bones(type='AUTOMATIC')
  119. bpy.ops.paint.weight_paint_toggle()
  120. #
  121. with bContext.temp_override(**{'active_object':armOb}):
  122. bpy.ops.object.mode_set(mode='POSE')
  123. bpy.ops.pose.select_all(action='DESELECT')
  124. bpy.ops.object.mode_set(mode='OBJECT')
  125. # TODO: modify Blender to make this available as a Python API function.
  126. if skin_method == "EXISTING_GROUPS":
  127. self.initialize_vgroups(use_existing = True)
  128. def __repr__(self):
  129. return self.signature.__repr__()
  130. def fill_parameters(self):
  131. fill_parameters(self)