diff --git a/rigify/generate.py b/rigify/generate.py index e1fd29b8f51762ea2ff405331a1f10a549af70c8..475c57feb2a1828c1b1b3a95ef63140c29bd2f78 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 5682ec64528ba857bf8c58c02fb85bb2febce7b7..a172b9849f4c9b83d26b9e3eea7f4acab45ba7f2 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 04e176c6e3c56f2b262cae916341b7df4491aedc..f198afdaca03c3fb5a3dd45bbde1a46ba641052e 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):