| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- from .node_container_common import *
- from .xForm_containers import xFormGeometryObject
- from bpy.types import Node
- from .base_definitions import MantisNode
- def TellClasses():
-
- return [
- DeformerArmature,
- ]
- def default_evaluate_input(nc, input_name):
- # duped from link_containers... should be common?
- # should catch 'Target', 'Pole Target' and ArmatureConstraint targets, too
- if ('Target' in input_name) and input_name != "Target Space":
- socket = nc.inputs.get(input_name)
- if socket.is_linked:
- return socket.links[0].from_node
- return None
-
- else:
- return evaluate_input(nc, input_name)
- # semi-duplicated from link_containers
- def GetxForm(nc):
- trace = trace_single_line_up(nc, "Deformer")
- for node in trace[0]:
- if (node.__class__ in [xFormGeometryObject]):
- return node
- raise GraphError("%s is not connected to a downstream xForm" % nc)
- class DeformerArmature:
- '''A node representing an armature deformer'''
- def __init__(self, signature, base_tree):
- self.base_tree=base_tree
- self.signature = signature
- self.inputs = {
- "Input Relationship" : NodeSocket(is_input = True, name = "Input Relationship", node = self,),
- "Target" : NodeSocket(is_input = True, name = "Target", node = self,),
- "Vertex Group" : NodeSocket(is_input = True, name = "Vertex Group", node = self),
- "Preserve Volume" : NodeSocket(is_input = True, name = "Preserve Volume", node = self),
- "Use Multi Modifier" : NodeSocket(is_input = True, name = "Use Multi Modifier", node = self),
- "Use Envelopes" : NodeSocket(is_input = True, name = "Use Envelopes", node = self),
- "Use Vertex Groups" : NodeSocket(is_input = True, name = "Use Vertex Groups", node = self),
- "Skinning Method" : NodeSocket(is_input = True, name = "Skinning Method", node = self),
- }
- self.outputs = {
- "Deformer" : NodeSocket(is_input = False, name = "Deformer", node=self), }
- self.parameters = {
- "Name" : None,
- "Target" : None,
- "Vertex Group" : None,
- "Preserve Volume" : None,
- "Use Multi Modifier" : None,
- "Use Envelopes" : None,
- "Use Vertex Groups" : None,
- "Skinning Method" : None,
- }
- # now set up the traverse target...
- self.inputs["Input Relationship"].set_traverse_target(self.outputs["Deformer"])
- self.outputs["Deformer"].set_traverse_target(self.inputs["Input Relationship"])
- self.node_type = "LINK"
- def evaluate_input(self, input_name):
- return default_evaluate_input(self, input_name)
- def GetxForm(self):
- return GetxForm(self)
- def bExecute(self, bContext = None,):
- prGreen("Executing Armature Deform Node\n")
- print(self.GetxForm())
- prOrange("My object: %s\n" % (self.GetxForm().bGetObject()))
- prepare_parameters(self)
- d = self.GetxForm().bGetObject().modifiers.new(self.evaluate_input("Name"), type='ARMATURE')
- self.bObject = d
- get_target_and_subtarget(self, d)
- props_sockets = {
- 'vertex_group' : ("Vertex Group", ""),
- 'use_deform_preserve_volume' : ("Preserve Volume", False),
- 'use_multi_modifier' : ("Use Multi Modifier", False),
- 'use_bone_envelopes' : ("Use Envelopes", False),
- 'use_vertex_groups' : ("Use Vertex Groups", False),
- }
- evaluate_sockets(self, d, props_sockets)
-
- def initialize_vgroups(self, use_existing = False):
- ob = self.GetxForm().bGetObject()
- if use_existing == False:
- ob.vertex_groups.clear()
- armOb = self.evaluate_input("Target").bGetObject()
- deform_bones = []
- for b in armOb.data.bones:
- if b.use_deform == True:
- deform_bones.append(b)
- for b in deform_bones:
- vg = ob.vertex_groups.get(b.name)
- if not vg:
- vg = ob.vertex_groups.new(name=b.name)
- num_verts = len(ob.data.vertices)
- vg.add(range(num_verts), 0, 'REPLACE')
-
-
- def bFinalize(self, bContext=None):
- if (skin_method := self.evaluate_input("Skinning Method")) == "AUTOMATIC_HEAT":
- # This is reatarded and leads to somewhat unpredictable
- # behaviour, e.g. what object will be selected? What mode?
- # also bpy.ops is ugly and prone to error when used in
- # scripts. I don't intend to use bpy.ops when I can avoid it.
- import bpy
- self.initialize_vgroups()
- bContext.view_layer.depsgraph.update()
- ob = self.GetxForm().bGetObject()
- armOb = self.evaluate_input("Target").bGetObject()
- deform_bones = []
- for pb in armOb.pose.bones:
- if pb.bone.use_deform == True:
- deform_bones.append(pb)
-
- context_override = {
- 'active_object':ob,
- 'selected_objects':[ob, armOb],
- 'active_pose_bone':deform_bones[0],
- 'selected_pose_bones':deform_bones,}
- #
- with bContext.temp_override(**{'active_object':armOb}):
- bpy.ops.object.mode_set(mode='POSE')
- bpy.ops.pose.select_all(action='SELECT')
- with bContext.temp_override(**context_override):
- bpy.ops.paint.weight_paint_toggle()
- bpy.ops.paint.weight_from_bones(type='AUTOMATIC')
- bpy.ops.paint.weight_paint_toggle()
- #
- with bContext.temp_override(**{'active_object':armOb}):
- bpy.ops.object.mode_set(mode='POSE')
- bpy.ops.pose.select_all(action='DESELECT')
- bpy.ops.object.mode_set(mode='OBJECT')
- # TODO: modify Blender to make this available as a Python API function.
- if skin_method == "EXISTING_GROUPS":
- self.initialize_vgroups(use_existing = True)
-
- def __repr__(self):
- return self.signature.__repr__()
- def fill_parameters(self):
- fill_parameters(self)
|