[Bf-extensions-cvs] [f8d6489f] master: Rigify: use separate widget collection for each generated rig.

Alexander Gavrilov noreply at git.blender.org
Mon Dec 7 21:38:55 CET 2020


Commit: f8d6489fb6e4b8f3c1029d3468ebbe6781f599dd
Author: Alexander Gavrilov
Date:   Mon Dec 7 22:11:00 2020 +0300
Branches: master
https://developer.blender.org/rBAf8d6489fb6e4b8f3c1029d3468ebbe6781f599dd

Rigify: use separate widget collection for each generated rig.

As pointed out in comments to T73114, using the same name has downsides.

In addition, remove the widget parent object that was inherited
from the old pre-collection way Rigify worked and has no other
purpose than grouping objects like the collection already does.

Rename the widgets and the collection when renaming the rig.

Finally as an aside add a couple of options to create_widget.

===================================================================

M	rigify/generate.py
M	rigify/utils/collections.py
M	rigify/utils/widgets.py

===================================================================

diff --git a/rigify/generate.py b/rigify/generate.py
index e1fd29b8..475c57fe 100644
--- a/rigify/generate.py
+++ b/rigify/generate.py
@@ -112,35 +112,47 @@ class Generator(base_generate.BaseGenerator):
         return obj
 
 
-    def __create_widget_group(self, new_group_name):
-        context = self.context
-        scene = self.scene
-        id_store = self.id_store
+    def __create_widget_group(self):
+        new_group_name = "WGTS_" + self.obj.name
+        wgts_group_name = "WGTS_" + (self.rig_old_name or self.obj.name)
 
-        # Create/find widge collection
-        self.widget_collection = ensure_widget_collection(context)
+        # Find the old widgets collection
+        old_collection = bpy.data.collections.get(wgts_group_name)
 
-        # Remove wgts if force update is set
-        wgts_group_name = "WGTS_" + (self.rig_old_name or self.obj.name)
-        if wgts_group_name in scene.objects and self.metarig.data.rigify_force_widget_update:
-            bpy.ops.object.mode_set(mode='OBJECT')
-            bpy.ops.object.select_all(action='DESELECT')
-            for wgt in bpy.data.objects[wgts_group_name].children:
-                wgt.select_set(True)
-            bpy.ops.object.delete(use_global=False)
+        if not old_collection:
+            # Update the old 'Widgets' collection
+            legacy_collection = bpy.data.collections.get('Widgets')
+
+            if legacy_collection and wgts_group_name in legacy_collection.objects:
+                legacy_collection.name = wgts_group_name
+                old_collection = legacy_collection
+
+        if old_collection:
+            # Remove widgets if force update is set
+            if self.metarig.data.rigify_force_widget_update:
+                for obj in list(old_collection.objects):
+                    bpy.data.objects.remove(obj)
+
+            # Rename widgets and collection if renaming
             if self.rig_old_name:
-                bpy.data.objects[wgts_group_name].name = new_group_name
+                old_prefix = WGT_PREFIX + self.rig_old_name + "_"
+                new_prefix = WGT_PREFIX + self.obj.name + "_"
 
-        # Create Group widget
-        wgts_group_name = new_group_name
-        if wgts_group_name not in scene.objects:
-            if wgts_group_name in bpy.data.objects:
-                bpy.data.objects[wgts_group_name].user_clear()
-                bpy.data.objects.remove(bpy.data.objects[wgts_group_name])
-            mesh = bpy.data.meshes.new(wgts_group_name)
-            wgts_obj = bpy.data.objects.new(wgts_group_name, mesh)
-            self.widget_collection.objects.link(wgts_obj)
+                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
+
+                    obj.data.name = new_name
+                    obj.name = new_name
+
+                old_collection.name = new_group_name
 
+        # Create/find widget collection
+        self.widget_collection = ensure_widget_collection(self.context, new_group_name)
         self.wgts_group_name = new_group_name
 
 
@@ -351,7 +363,7 @@ class Generator(base_generate.BaseGenerator):
 
         #------------------------------------------
         # Create Group widget
-        self.__create_widget_group("WGTS_" + obj.name)
+        self.__create_widget_group()
 
         t.tick("Create main WGTS: ")
 
diff --git a/rigify/utils/collections.py b/rigify/utils/collections.py
index 5682ec64..a172b984 100644
--- a/rigify/utils/collections.py
+++ b/rigify/utils/collections.py
@@ -65,9 +65,7 @@ def filter_layer_collections_by_object(layer_collections, obj):
     return [lc for lc in layer_collections if obj in lc.collection.objects.values()]
 
 
-def ensure_widget_collection(context):
-    wgts_collection_name = "Widgets"
-
+def ensure_widget_collection(context, wgts_collection_name):
     view_layer = context.view_layer
     layer_collection = bpy.context.layer_collection
     collection = layer_collection.collection
@@ -89,6 +87,8 @@ def ensure_widget_collection(context):
         collection.children.link(widget_collection)
         widget_layer_collection = [c for c in layer_collection.children if c.collection == widget_collection][0]
 
+        widget_layer_collection.exclude = True
+
     # Make the widget the active collection for the upcoming added (widget) objects
     view_layer.active_layer_collection = widget_layer_collection
     return widget_collection
diff --git a/rigify/utils/widgets.py b/rigify/utils/widgets.py
index 04e176c6..f198afda 100644
--- a/rigify/utils/widgets.py
+++ b/rigify/utils/widgets.py
@@ -54,7 +54,7 @@ def obj_to_bone(obj, rig, bone_name, bone_transform_name=None):
     obj.matrix_basis = rig.matrix_world @ bone.bone.matrix_local @ Matrix.Scale(scale, 4)
 
 
-def create_widget(rig, bone_name, bone_transform_name=None):
+def create_widget(rig, bone_name, bone_transform_name=None, *, widget_name=None, widget_force_new=False):
     """ Creates an empty widget object for a bone, and returns the object.
     """
     assert rig.mode != 'EDIT'
@@ -64,37 +64,34 @@ def create_widget(rig, bone_name, bone_transform_name=None):
     if bone.custom_shape:
         return None
 
-    obj_name = WGT_PREFIX + rig.name + '_' + bone_name
+    obj_name = widget_name or WGT_PREFIX + rig.name + '_' + bone_name
     scene = bpy.context.scene
-    collection = ensure_widget_collection(bpy.context)
+    collection = ensure_widget_collection(bpy.context, 'WGTS_' + rig.name)
 
     # Check if it already exists in the scene
-    if obj_name in scene.objects:
-        # Move object to bone position, in case it changed
-        obj = scene.objects[obj_name]
-        obj_to_bone(obj, rig, bone_name, bone_transform_name)
+    if not widget_force_new:
+        if obj_name in scene.objects:
+            # Move object to bone position, in case it changed
+            obj = scene.objects[obj_name]
+            obj_to_bone(obj, rig, bone_name, bone_transform_name)
+
+            return None
 
-        return None
-    else:
         # Delete object if it exists in blend data but not scene data.
         # This is necessary so we can then create the object without
         # name conflicts.
         if obj_name in bpy.data.objects:
-            bpy.data.objects[obj_name].user_clear()
             bpy.data.objects.remove(bpy.data.objects[obj_name])
 
-        # Create mesh object
-        mesh = bpy.data.meshes.new(obj_name)
-        obj = bpy.data.objects.new(obj_name, mesh)
-        collection.objects.link(obj)
+    # Create mesh object
+    mesh = bpy.data.meshes.new(obj_name)
+    obj = bpy.data.objects.new(obj_name, mesh)
+    collection.objects.link(obj)
 
-        # Move object to bone position and set layers
-        obj_to_bone(obj, rig, bone_name, bone_transform_name)
-        wgts_group_name = 'WGTS_' + rig.name
-        if wgts_group_name in bpy.data.objects.keys():
-            obj.parent = bpy.data.objects[wgts_group_name]
+    # Move object to bone position and set layers
+    obj_to_bone(obj, rig, bone_name, bone_transform_name)
 
-        return obj
+    return obj
 
 
 def create_circle_polygon(number_verts, axis, radius=1.0, head_tail=0.0):



More information about the Bf-extensions-cvs mailing list