Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Gavrilov <angavrilov@gmail.com>2021-09-20 22:16:41 +0300
committerAlexander Gavrilov <angavrilov@gmail.com>2021-09-20 22:34:09 +0300
commiteed6d6cc132d194efe018996d43a36ebc8d91ad4 (patch)
tree0817ea53fe929cb2959e219d1076d998d9d22b61 /rigify/generate.py
parentecf30de46c368ffddad259c125402a38e6093382 (diff)
Rigify: support generating mirrored linked duplicate widgets.
After the custom shape scale property was split into an XYZ vector, it is possible to generate truly mirrored widgets using the same mesh for the left and right side. The widgets Rigify generates are originally symmetrical, but in practice they usually need to be tweaked to fit the character better, and proper mirroring matters. This commit implements widget mirroring and enables it by default. When reusing widgets left from a previous generation the code tries to detect whether they were actually originally mirrored by checking object scale to avoid flipping in pre-existing rigs. As an aside, reusing pre-existing widgets is made more robust to random name changes by building a table via scanning the old generated rig before overwriting it.
Diffstat (limited to 'rigify/generate.py')
-rw-r--r--rigify/generate.py58
1 files changed, 40 insertions, 18 deletions
diff --git a/rigify/generate.py b/rigify/generate.py
index ad8f43b5..a2d9a5d1 100644
--- a/rigify/generate.py
+++ b/rigify/generate.py
@@ -25,7 +25,7 @@ import time
from .utils.errors import MetarigError
from .utils.bones import new_bone
from .utils.layers import ORG_LAYER, MCH_LAYER, DEF_LAYER, ROOT_LAYER
-from .utils.naming import ORG_PREFIX, MCH_PREFIX, DEF_PREFIX, ROOT_NAME, make_original_name
+from .utils.naming import ORG_PREFIX, MCH_PREFIX, DEF_PREFIX, ROOT_NAME, make_original_name, change_name_side, get_name_side, Side
from .utils.widgets import WGT_PREFIX
from .utils.widgets_special import create_root_widget
from .utils.mechanism import refresh_all_drivers
@@ -165,27 +165,44 @@ class Generator(base_generate.BaseGenerator):
for obj in list(old_collection.objects):
bpy.data.objects.remove(obj)
- # Rename widgets and collection if renaming
- if self.rig_old_name:
- old_prefix = WGT_PREFIX + self.rig_old_name + "_"
- new_prefix = WGT_PREFIX + self.obj.name + "_"
+ # Rename the collection
+ old_collection.name = new_group_name
- for obj in list(old_collection.objects):
- if obj.name.startswith(old_prefix):
- new_name = new_prefix + obj.name[len(old_prefix):]
- elif obj.name == wgts_group_name:
- new_name = new_group_name
- else:
- continue
+ # Create/find widget collection
+ self.widget_collection = ensure_widget_collection(self.context, new_group_name)
+ self.use_mirror_widgets = self.metarig.data.rigify_mirror_widgets
- obj.data.name = new_name
- obj.name = new_name
+ # Build tables for existing widgets
+ self.old_widget_table = {}
+ self.new_widget_table = {}
+ self.widget_mirror_mesh = {}
- old_collection.name = new_group_name
+ if not self.metarig.data.rigify_force_widget_update and self.obj.pose:
+ # Find all widgets from the collection referenced by the old rig
+ known_widgets = set(obj.name for obj in self.widget_collection.objects)
- # Create/find widget collection
- self.widget_collection = ensure_widget_collection(self.context, new_group_name)
- self.wgts_group_name = new_group_name
+ for bone in self.obj.pose.bones:
+ if bone.custom_shape and bone.custom_shape.name in known_widgets:
+ self.old_widget_table[bone.name] = bone.custom_shape
+
+ # Rename widgets in case the rig was renamed
+ name_prefix = WGT_PREFIX + self.obj.name + "_"
+
+ for bone_name, widget in self.old_widget_table.items():
+ old_data_name = change_name_side(widget.name, get_name_side(widget.data.name))
+
+ widget.name = name_prefix + bone_name
+
+ # If the mesh name is the same as the object, rename it too
+ if widget.data.name == old_data_name:
+ widget.data.name = change_name_side(widget.name, get_name_side(widget.data.name))
+
+ # Find meshes for mirroring
+ if self.use_mirror_widgets:
+ for bone_name, widget in self.old_widget_table.items():
+ mid_name = change_name_side(bone_name, Side.MIDDLE)
+ if bone_name != mid_name:
+ self.widget_mirror_mesh[mid_name] = widget.data
def __duplicate_rig(self):
@@ -373,6 +390,11 @@ class Generator(base_generate.BaseGenerator):
# Assign shapes to bones
# Object's with name WGT-<bone_name> get used as that bone's shape.
for bone in self.obj.pose.bones:
+ # First check the table built by create_widget
+ if bone.name in self.new_widget_table:
+ bone.custom_shape = self.new_widget_table[bone.name]
+ continue
+
# Object names are limited to 63 characters... arg
wgt_name = (WGT_PREFIX + self.obj.name + '_' + bone.name)[:63]