Skip to content
Snippets Groups Projects
Commit c93dc355 authored by Alexander Gavrilov's avatar Alexander Gavrilov
Browse files

Rigify: keep custom widgets already assigned in metarig.

Also make error handling more robust and extend constraint relink mixin.
parent 53bfa6c9
No related branches found
No related tags found
No related merge requests found
...@@ -338,7 +338,7 @@ class BaseGenerator: ...@@ -338,7 +338,7 @@ class BaseGenerator:
self.__run_edit_stage('prepare_bones') self.__run_edit_stage('prepare_bones')
def __auto_register_bones(self, bones, rig): def __auto_register_bones(self, bones, rig, plugin=None):
"""Find bones just added and not registered by this rig.""" """Find bones just added and not registered by this rig."""
for bone in bones: for bone in bones:
name = bone.name name = bone.name
...@@ -347,8 +347,10 @@ class BaseGenerator: ...@@ -347,8 +347,10 @@ class BaseGenerator:
if rig: if rig:
rig.rigify_new_bones[name] = None rig.rigify_new_bones[name] = None
if not isinstance(rig, LegacyRig): if not isinstance(rig, LegacyRig):
print("WARNING: rig %s didn't register bone %s\n" % (self.describe_rig(rig), name)) print("WARNING: rig %s didn't register bone %s\n" % (self.describe_rig(rig), name))
else:
print("WARNING: plugin %s didn't register bone %s\n" % (plugin, name))
def invoke_generate_bones(self): def invoke_generate_bones(self):
...@@ -365,13 +367,17 @@ class BaseGenerator: ...@@ -365,13 +367,17 @@ class BaseGenerator:
self.__auto_register_bones(self.obj.data.edit_bones, rig) self.__auto_register_bones(self.obj.data.edit_bones, rig)
for plugin in self.plugin_list: # Allow plugins to be added to the end of the list on the fly
plugin.rigify_invoke_stage('generate_bones') for i in count(0):
if i >= len(self.plugin_list):
break
self.plugin_list[i].rigify_invoke_stage('generate_bones')
assert(self.context.active_object == self.obj) assert(self.context.active_object == self.obj)
assert(self.obj.mode == 'EDIT') assert(self.obj.mode == 'EDIT')
self.__auto_register_bones(self.obj.data.edit_bones, None) self.__auto_register_bones(self.obj.data.edit_bones, None, plugin=self.plugin_list[i])
def invoke_parent_bones(self): def invoke_parent_bones(self):
......
...@@ -47,10 +47,19 @@ class RelinkConstraintsMixin: ...@@ -47,10 +47,19 @@ class RelinkConstraintsMixin:
def relink_bone_constraints(self, bone_name): def relink_bone_constraints(self, bone_name):
if self.params.relink_constraints: if self.params.relink_constraints:
for con in self.get_bone(bone_name).constraints: for con in self.get_bone(bone_name).constraints:
parts = con.name.split('@') self.relink_single_constraint(con)
if len(parts) > 1:
self.relink_constraint(con, parts[1:]) relink_unmarked_constraints = False
def relink_single_constraint(self, con):
if self.params.relink_constraints:
parts = con.name.split('@')
if len(parts) > 1:
self.relink_constraint(con, parts[1:])
elif self.relink_unmarked_constraints:
self.relink_constraint(con, [''])
def relink_bone_parent(self, bone_name): def relink_bone_parent(self, bone_name):
...@@ -73,13 +82,15 @@ class RelinkConstraintsMixin: ...@@ -73,13 +82,15 @@ class RelinkConstraintsMixin:
self.raise_error("Constraint {} actually has {} targets", con.name, len(con.targets)) self.raise_error("Constraint {} actually has {} targets", con.name, len(con.targets))
for tgt, spec in zip(con.targets, specs): for tgt, spec in zip(con.targets, specs):
tgt.subtarget = self.find_relink_target(spec, tgt.subtarget) if tgt.target == self.obj:
tgt.subtarget = self.find_relink_target(spec, tgt.subtarget)
else: elif hasattr(con, 'subtarget'):
if len(specs) > 1: if len(specs) > 1:
self.raise_error("Only the Armature constraint can have multiple '@' targets: {}", con.name) self.raise_error("Only the Armature constraint can have multiple '@' targets: {}", con.name)
con.subtarget = self.find_relink_target(specs[0], con.subtarget) if con.target == self.obj:
con.subtarget = self.find_relink_target(specs[0], con.subtarget)
def find_relink_target(self, spec, old_target): def find_relink_target(self, spec, old_target):
......
...@@ -608,10 +608,10 @@ class BONE_PT_rigify_buttons(bpy.types.Panel): ...@@ -608,10 +608,10 @@ class BONE_PT_rigify_buttons(bpy.types.Panel):
if rig_name != "": if rig_name != "":
try: try:
rig = rig_lists.rigs[rig_name]['module'] rig = rig_lists.rigs[rig_name]['module']
except (ImportError, AttributeError): except (ImportError, AttributeError, KeyError):
row = layout.row() row = layout.row()
box = row.box() box = row.box()
box.label(text="ALERT: type \"%s\" does not exist!" % rig_name) box.label(text="ERROR: type \"%s\" does not exist!" % rig_name, icon='ERROR')
else: else:
if hasattr(rig.Rig, 'parameters_ui'): if hasattr(rig.Rig, 'parameters_ui'):
rig = rig.Rig rig = rig.Rig
...@@ -828,7 +828,7 @@ class Sample(bpy.types.Operator): ...@@ -828,7 +828,7 @@ class Sample(bpy.types.Operator):
try: try:
rig = rig_lists.rigs[self.metarig_type]["module"] rig = rig_lists.rigs[self.metarig_type]["module"]
create_sample = rig.create_sample create_sample = rig.create_sample
except (ImportError, AttributeError): except (ImportError, AttributeError, KeyError):
raise Exception("rig type '" + self.metarig_type + "' has no sample.") raise Exception("rig type '" + self.metarig_type + "' has no sample.")
else: else:
create_sample(context.active_object) create_sample(context.active_object)
......
...@@ -174,7 +174,7 @@ def copy_bone(obj, bone_name, assign_name='', *, parent=False, inherit_scale=Fal ...@@ -174,7 +174,7 @@ def copy_bone(obj, bone_name, assign_name='', *, parent=False, inherit_scale=Fal
raise MetarigError("Cannot copy bones outside of edit mode") raise MetarigError("Cannot copy bones outside of edit mode")
def copy_bone_properties(obj, bone_name_1, bone_name_2): def copy_bone_properties(obj, bone_name_1, bone_name_2, transforms=True, props=True, widget=True):
""" Copy transform and custom properties from bone 1 to bone 2. """ """ Copy transform and custom properties from bone 1 to bone 2. """
if obj.mode in {'OBJECT','POSE'}: if obj.mode in {'OBJECT','POSE'}:
# Get the pose bones # Get the pose bones
...@@ -182,28 +182,33 @@ def copy_bone_properties(obj, bone_name_1, bone_name_2): ...@@ -182,28 +182,33 @@ def copy_bone_properties(obj, bone_name_1, bone_name_2):
pose_bone_2 = obj.pose.bones[bone_name_2] pose_bone_2 = obj.pose.bones[bone_name_2]
# Copy pose bone attributes # Copy pose bone attributes
pose_bone_2.rotation_mode = pose_bone_1.rotation_mode if transforms:
pose_bone_2.rotation_axis_angle = tuple(pose_bone_1.rotation_axis_angle) pose_bone_2.rotation_mode = pose_bone_1.rotation_mode
pose_bone_2.rotation_euler = tuple(pose_bone_1.rotation_euler) pose_bone_2.rotation_axis_angle = tuple(pose_bone_1.rotation_axis_angle)
pose_bone_2.rotation_quaternion = tuple(pose_bone_1.rotation_quaternion) pose_bone_2.rotation_euler = tuple(pose_bone_1.rotation_euler)
pose_bone_2.rotation_quaternion = tuple(pose_bone_1.rotation_quaternion)
pose_bone_2.lock_location = tuple(pose_bone_1.lock_location)
pose_bone_2.lock_scale = tuple(pose_bone_1.lock_scale) pose_bone_2.lock_location = tuple(pose_bone_1.lock_location)
pose_bone_2.lock_rotation = tuple(pose_bone_1.lock_rotation) pose_bone_2.lock_scale = tuple(pose_bone_1.lock_scale)
pose_bone_2.lock_rotation_w = pose_bone_1.lock_rotation_w pose_bone_2.lock_rotation = tuple(pose_bone_1.lock_rotation)
pose_bone_2.lock_rotations_4d = pose_bone_1.lock_rotations_4d pose_bone_2.lock_rotation_w = pose_bone_1.lock_rotation_w
pose_bone_2.lock_rotations_4d = pose_bone_1.lock_rotations_4d
# Copy custom properties # Copy custom properties
for key in pose_bone_1.keys(): if props:
if key != "_RNA_UI" \ for key in pose_bone_1.keys():
and key != "rigify_parameters" \ if key != "_RNA_UI" \
and key != "rigify_type": and key != "rigify_parameters" \
prop1 = rna_idprop_ui_prop_get(pose_bone_1, key, create=False) and key != "rigify_type":
pose_bone_2[key] = pose_bone_1[key] prop1 = rna_idprop_ui_prop_get(pose_bone_1, key, create=False)
if prop1 is not None: pose_bone_2[key] = pose_bone_1[key]
prop2 = rna_idprop_ui_prop_get(pose_bone_2, key, create=True) if prop1 is not None:
for key in prop1.keys(): prop2 = rna_idprop_ui_prop_get(pose_bone_2, key, create=True)
prop2[key] = prop1[key] for key in prop1.keys():
prop2[key] = prop1[key]
if widget:
pose_bone_2.custom_shape = pose_bone_1.custom_shape
else: else:
raise MetarigError("Cannot copy bone properties in edit mode") raise MetarigError("Cannot copy bone properties in edit mode")
...@@ -393,9 +398,9 @@ class BoneUtilityMixin(object): ...@@ -393,9 +398,9 @@ class BoneUtilityMixin(object):
self.register_new_bone(name, bone_name) self.register_new_bone(name, bone_name)
return name return name
def copy_bone_properties(self, src_name, tgt_name): def copy_bone_properties(self, src_name, tgt_name, **kwargs):
"""Copy pose-mode properties of the bone.""" """Copy pose-mode properties of the bone."""
copy_bone_properties(self.obj, src_name, tgt_name) copy_bone_properties(self.obj, src_name, tgt_name, **kwargs)
def rename_bone(self, old_name, new_name): def rename_bone(self, old_name, new_name):
"""Rename the bone, returning the actual new name.""" """Rename the bone, returning the actual new name."""
......
...@@ -57,6 +57,13 @@ def obj_to_bone(obj, rig, bone_name, bone_transform_name=None): ...@@ -57,6 +57,13 @@ def obj_to_bone(obj, rig, bone_name, bone_transform_name=None):
def create_widget(rig, bone_name, bone_transform_name=None): def create_widget(rig, bone_name, bone_transform_name=None):
""" Creates an empty widget object for a bone, and returns the object. """ Creates an empty widget object for a bone, and returns the object.
""" """
assert rig.mode != 'EDIT'
bone = rig.pose.bones[bone_name]
# The bone already has a widget
if bone.custom_shape:
return None
obj_name = WGT_PREFIX + rig.name + '_' + bone_name obj_name = WGT_PREFIX + rig.name + '_' + bone_name
scene = bpy.context.scene scene = bpy.context.scene
collection = ensure_widget_collection(bpy.context) collection = ensure_widget_collection(bpy.context)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment