diff --git a/rigify/__init__.py b/rigify/__init__.py
index 019adb48f6f90dfb1faa3c54a457d82ae4c33875..20e18a42224d39d38fc0b89c137276a00f14533a 100644
--- a/rigify/__init__.py
+++ b/rigify/__init__.py
@@ -512,20 +512,6 @@ def register():
     IDStore.rigify_types = CollectionProperty(type=RigifyName)
     IDStore.rigify_active_type = IntProperty(name="Rigify Active Type", description="The selected rig type")
 
-    bpy.types.Armature.rigify_advanced_generation = BoolProperty(name="Advanced Options",
-        description="Enables/disables advanced options for Rigify rig generation",
-        default=False)
-
-    def update_mode(self, context):
-        if self.rigify_generate_mode == 'new':
-            self.rigify_force_widget_update = False
-
-    bpy.types.Armature.rigify_generate_mode = EnumProperty(name="Rigify Generate Rig Mode",
-        description="'Generate Rig' mode. In 'overwrite' mode the features of the target rig will be updated as defined by the metarig. In 'new' mode a new rig will be created as defined by the metarig. Current mode",
-        update=update_mode,
-        items=( ('overwrite', 'overwrite', ''),
-                ('new', 'new', '')))
-
     bpy.types.Armature.rigify_force_widget_update = BoolProperty(name="Force Widget Update",
         description="Forces Rigify to delete and rebuild all the rig widgets. if unset, only missing widgets will be created",
         default=False)
@@ -533,6 +519,9 @@ def register():
     bpy.types.Armature.rigify_mirror_widgets = BoolProperty(name="Mirror Widgets",
         description="Make widgets for left and right side bones linked duplicates with negative X scale for the right side, based on bone name symmetry",
         default=True)
+    bpy.types.Armature.rigify_widgets_collection = PointerProperty(type=bpy.types.Collection,
+        name="Widgets Collection",
+        description="Defines which collection to place widget objects in. If unset, a new one will be created based on the name of the rig")
 
     bpy.types.Armature.rigify_target_rig = PointerProperty(type=bpy.types.Object,
         name="Rigify Target Rig",
@@ -546,11 +535,6 @@ def register():
     bpy.types.Armature.rigify_finalize_script = PointerProperty(type=bpy.types.Text,
         name="Finalize Script",
         description="Run this script after generation to apply user-specific changes")
-
-    bpy.types.Armature.rigify_rig_basename = StringProperty(name="Rigify Rig Name",
-        description="Defines the name of the Rig. If unset, in 'new' mode 'rig' will be used, in 'overwrite' mode the target rig name will be used",
-        default="")
-
     IDStore.rigify_transfer_only_selected = BoolProperty(
         name="Transfer Only Selected",
         description="Transfer selected bones only", default=True)
@@ -592,12 +576,9 @@ def unregister():
     del ArmStore.rigify_colors_index
     del ArmStore.rigify_colors_lock
     del ArmStore.rigify_theme_to_add
-    del ArmStore.rigify_advanced_generation
-    del ArmStore.rigify_generate_mode
     del ArmStore.rigify_force_widget_update
     del ArmStore.rigify_target_rig
     del ArmStore.rigify_rig_ui
-    del ArmStore.rigify_rig_basename
 
     IDStore = bpy.types.WindowManager
     del IDStore.rigify_collection
diff --git a/rigify/generate.py b/rigify/generate.py
index 501c335fadfcaded7baaa6bc51a612d32de0f574..a674ade447c81ec714c786d62b0b01af1d017ce1 100644
--- a/rigify/generate.py
+++ b/rigify/generate.py
@@ -30,7 +30,7 @@ from .utils.widgets import WGT_PREFIX
 from .utils.widgets_special import create_root_widget
 from .utils.mechanism import refresh_all_drivers
 from .utils.misc import gamma_correct, select_object
-from .utils.collections import ensure_widget_collection, list_layer_collections, filter_layer_collections_by_object
+from .utils.collections import ensure_collection, list_layer_collections, filter_layer_collections_by_object
 from .utils.rig import get_rigify_type
 
 from . import base_generate
@@ -55,9 +55,6 @@ class Generator(base_generate.BaseGenerator):
 
         self.id_store = context.window_manager
 
-        self.rig_new_name = ""
-        self.rig_old_name = ""
-
 
     def find_rig_class(self, rig_type):
         rig_module = rig_lists.rigs[rig_type]["module"]
@@ -76,55 +73,42 @@ class Generator(base_generate.BaseGenerator):
         self.collection = self.layer_collection.collection
 
 
-    def __create_rig_object(self):
-        scene = self.scene
-        id_store = self.id_store
-        meta_data = self.metarig.data
-
-        # Check if the generated rig already exists, so we can
-        # regenerate in the same object.  If not, create a new
-        # object to generate the rig in.
+    def ensure_rig_object(self) -> bpy.types.Object:
+        """Check if the generated rig already exists, so we can
+        regenerate in the same object. If not, create a new
+        object to generate the rig in.
+        """
         print("Fetch rig.")
+        meta_data = self.metarig.data
 
-        self.rig_new_name = name = meta_data.rigify_rig_basename or "rig"
-
-        obj = None
-
-        # Try existing object if overwriting
-        if meta_data.rigify_generate_mode == 'overwrite':
-            obj = meta_data.rigify_target_rig
-
-            if obj:
-                self.rig_old_name = obj.name
-
-                obj.name = name
-                obj.data.name = obj.name
-
-            elif name in bpy.data.objects:
-                obj = bpy.data.objects[name]
+        target_rig = meta_data.rigify_target_rig
+        if not target_rig:
+            if "metarig" in self.metarig.name:
+                rig_new_name = self.metarig.name.replace("metarig", "rig")
+            elif "META" in self.metarig.name:
+                rig_new_name = self.metarig.name.replace("META", "RIG")
+            else:
+                rig_new_name = "RIG-" + self.metarig.name
 
-        # Create a new object if not found
-        if not obj:
-            obj = bpy.data.objects.new(name, bpy.data.armatures.new(name))
-            obj.display_type = 'WIRE'
+            target_rig = bpy.data.objects.new(rig_new_name, bpy.data.armatures.new(rig_new_name))
+            target_rig.display_type = 'WIRE'
 
         # If the object is already added to the scene, switch to its collection
-        if obj.name in self.context.scene.collection.all_objects:
-            self.__switch_to_usable_collection(obj)
+        if target_rig.name in self.context.scene.collection.all_objects:
+            self.__switch_to_usable_collection(target_rig)
         else:
             # Otherwise, add to the selected collection or the metarig collection if unusable
             if (self.layer_collection not in self.usable_collections
                 or self.layer_collection == self.view_layer.layer_collection):
                 self.__switch_to_usable_collection(self.metarig, True)
 
-            self.collection.objects.link(obj)
+            self.collection.objects.link(target_rig)
 
         # Configure and remember the object
-        meta_data.rigify_target_rig = obj
-        obj.data.pose_position = 'POSE'
+        meta_data.rigify_target_rig = target_rig
+        target_rig.data.pose_position = 'POSE'
 
-        self.obj = obj
-        return obj
+        return target_rig
 
 
     def __unhide_rig_object(self, obj):
@@ -144,11 +128,11 @@ class Generator(base_generate.BaseGenerator):
             raise Exception('Could not generate: Could not find a usable collection.')
 
 
-    def __create_widget_group(self):
-        new_group_name = "WGTS_" + self.obj.name
-        wgts_group_name = "WGTS_" + (self.rig_old_name or self.obj.name)
-
-        # Find the old widgets collection
+    def __find_legacy_collection(self) -> bpy.types.Collection:
+        """For backwards comp, matching by name to find a legacy collection.
+        (For before there was a Widget Collection PointerProperty)
+        """
+        wgts_group_name = "WGTS_" + self.obj.name
         old_collection = bpy.data.collections.get(wgts_group_name)
 
         if not old_collection:
@@ -160,16 +144,22 @@ class Generator(base_generate.BaseGenerator):
                 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 the collection
-            old_collection.name = new_group_name
+            old_collection.name = wgts_group_name
+        
+        return old_collection
 
+    def ensure_widget_collection(self):
         # Create/find widget collection
-        self.widget_collection = ensure_widget_collection(self.context, new_group_name)
+        self.widget_collection = self.metarig.data.rigify_widgets_collection
+        if not self.widget_collection:
+            self.widget_collection = self.__find_legacy_collection()
+        if not self.widget_collection:
+            wgts_group_name = "WGTS_" + self.obj.name.replace("RIG-", "")
+            self.widget_collection = ensure_collection(self.context, wgts_group_name, hidden=True)
+
+        self.metarig.data.rigify_widgets_collection = self.widget_collection
+
         self.use_mirror_widgets = self.metarig.data.rigify_mirror_widgets
 
         # Build tables for existing widgets
@@ -177,7 +167,11 @@ class Generator(base_generate.BaseGenerator):
         self.new_widget_table = {}
         self.widget_mirror_mesh = {}
 
-        if not self.metarig.data.rigify_force_widget_update and self.obj.pose:
+        if self.metarig.data.rigify_force_widget_update:
+            # Remove widgets if force update is set
+            for obj in list(self.widget_collection.objects):
+                bpy.data.objects.remove(obj)
+        elif 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)
 
@@ -430,7 +424,7 @@ class Generator(base_generate.BaseGenerator):
 
         #------------------------------------------
         # Create/find the rig object and set it up
-        obj = self.__create_rig_object()
+        self.obj = obj = self.ensure_rig_object()
 
         self.__unhide_rig_object(obj)
 
@@ -446,8 +440,8 @@ class Generator(base_generate.BaseGenerator):
         select_object(context, obj, deselect_all=True)
 
         #------------------------------------------
-        # Create Group widget
-        self.__create_widget_group()
+        # Create Widget Collection
+        self.ensure_widget_collection()
 
         t.tick("Create main WGTS: ")
 
diff --git a/rigify/rig_ui_template.py b/rigify/rig_ui_template.py
index c83dd02b9302c11f9ee7a596d1f349270c03e5f3..8780461de0162354e3033df13f306af29cddc410 100644
--- a/rigify/rig_ui_template.py
+++ b/rigify/rig_ui_template.py
@@ -1167,27 +1167,10 @@ class ScriptGenerator(base_generate.GeneratorPlugin):
             layer_layout += [(l.name, l.row)]
 
         # Generate the UI script
-        if metarig.data.rigify_rig_basename:
-            rig_ui_name = metarig.data.rigify_rig_basename + '_ui.py'
-        else:
-            rig_ui_name = 'rig_ui.py'
-
-        script = None
-
-        if metarig.data.rigify_generate_mode == 'overwrite':
-            script = metarig.data.rigify_rig_ui
-
-            if not script and rig_ui_name in bpy.data.texts:
-                script = bpy.data.texts[rig_ui_name]
-
-            if script:
-                script.clear()
-                script.name = rig_ui_name
-
-        if script is None:
-            script = bpy.data.texts.new(rig_ui_name)
-
-        metarig.data.rigify_rig_ui = script
+        script = metarig.data.rigify_rig_ui
+        if not script:
+            script = bpy.data.texts.new("rig_ui.py")
+            metarig.data.rigify_rig_ui = script
 
         for s in OrderedDict.fromkeys(self.ui_imports):
             script.write(s + "\n")
diff --git a/rigify/ui.py b/rigify/ui.py
index c801ac25c1ae3e4181c1ae2744805615203d5e7c..59dbf9b60809e47dbbb13226d467757915b20d8b 100644
--- a/rigify/ui.py
+++ b/rigify/ui.py
@@ -60,27 +60,27 @@ def build_type_list(context, rigify_types):
             a.name = r
 
 
-class DATA_PT_rigify_buttons(bpy.types.Panel):
-    bl_label = "Rigify Buttons"
+class DATA_PT_rigify_generate(bpy.types.Panel):
+    bl_label = "Rigify Generation"
     bl_space_type = 'PROPERTIES'
     bl_region_type = 'WINDOW'
     bl_context = "data"
 
     @classmethod
     def poll(cls, context):
+        obj = context.object
         if not context.object:
             return False
-        return context.object.type == 'ARMATURE' and context.active_object.data.get("rig_id") is None
+        return obj.type == 'ARMATURE' \
+            and obj.data.get("rig_id") is None \
+            and obj.mode in {'POSE', 'OBJECT'}
 
     def draw(self, context):
         C = context
         layout = self.layout
-        obj = context.object
-        id_store = C.window_manager
+        obj = C.object
 
         if obj.mode in {'POSE', 'OBJECT'}:
-            armature_id_store = C.object.data
-
             WARNING = "Warning: Some features may change after generation"
             show_warning = False
             show_update_metarig = False
@@ -110,7 +110,7 @@ class DATA_PT_rigify_buttons(bpy.types.Panel):
             if show_warning:
                 layout.label(text=WARNING, icon='ERROR')
 
-            enable_generate_and_advanced = not (show_not_updatable or show_update_metarig)
+            enable_generate = not (show_not_updatable or show_update_metarig)
 
             if show_not_updatable:
                 layout.label(text="WARNING: This metarig contains deprecated rigify rig-types and cannot be upgraded automatically.", icon='ERROR')
@@ -131,71 +131,74 @@ class DATA_PT_rigify_buttons(bpy.types.Panel):
 
             col.separator()
             row = col.row()
-            row.operator("pose.rigify_generate", text="Generate Rig", icon='POSE_HLT')
+            text = "Re-Generate Rig" if obj.data.rigify_target_rig else "Generate Rig"
+            row.operator("pose.rigify_generate", text=text, icon='POSE_HLT')
+            row.enabled = enable_generate
 
-            row.enabled = enable_generate_and_advanced
 
-            if armature_id_store.rigify_advanced_generation:
-                icon = 'UNLOCKED'
-            else:
-                icon = 'LOCKED'
+class DATA_PT_rigify_generate_advanced(bpy.types.Panel):
+    bl_space_type = 'PROPERTIES'
+    bl_region_type = 'WINDOW'
+    bl_context = "data"
+    bl_label = "Advanced"
+    bl_parent_id = 'DATA_PT_rigify_generate'
+    bl_options = {'DEFAULT_CLOSED'}
 
-            col = layout.column()
-            col.enabled = enable_generate_and_advanced
-            row = col.row()
-            row.prop(armature_id_store, "rigify_advanced_generation", toggle=True, icon=icon)
+    def draw(self, context):
+        layout = self.layout
+        layout.use_property_split = True
+        layout.use_property_decorate = False
 
-            if armature_id_store.rigify_advanced_generation:
+        armature_id_store = context.object.data
 
-                row = col.row(align=True)
-                row.prop(armature_id_store, "rigify_generate_mode", expand=True)
-
-                main_row = col.row(align=True).split(factor=0.3)
-                col1 = main_row.column()
-                col2 = main_row.column()
-                col1.label(text="Rig Name")
-                row = col1.row()
-                row.label(text="Target Rig")
-                row.enabled = (armature_id_store.rigify_generate_mode == "overwrite")
-                row = col1.row()
-                row.label(text="Target UI")
-                row.enabled = (armature_id_store.rigify_generate_mode == "overwrite")
-
-                row = col2.row(align=True)
-                row.prop(armature_id_store, "rigify_rig_basename", text="", icon="SORTALPHA")
-
-                row = col2.row(align=True)
-                row.prop(armature_id_store, "rigify_target_rig", text="")
-                row.enabled = (armature_id_store.rigify_generate_mode == "overwrite")
-
-                row = col2.row()
-                row.prop(armature_id_store, "rigify_rig_ui", text="", icon='TEXT')
-                row.enabled = (armature_id_store.rigify_generate_mode == "overwrite")
-
-                row = col.row()
-                row.prop(armature_id_store, "rigify_force_widget_update")
-                if armature_id_store.rigify_generate_mode == 'new':
-                    row.enabled = False
-
-                col.prop(armature_id_store, "rigify_mirror_widgets")
-                col.prop(armature_id_store, "rigify_finalize_script", text="Run Script")
-
-        elif obj.mode == 'EDIT':
-            # Build types list
-            build_type_list(context, id_store.rigify_types)
-
-            if id_store.rigify_active_type > len(id_store.rigify_types):
-                id_store.rigify_active_type = 0
-
-            # Rig type list
-            if len(feature_set_list.get_installed_list()) > 0:
-                row = layout.row()
-                row.prop(context.object.data, "active_feature_set")
+        col = layout.column()
+        col.row().prop(armature_id_store, "rigify_target_rig", text="Target Rig")
+        col.row().prop(armature_id_store, "rigify_rig_ui", text="Rig UI Script")
+        col.separator()
+        col.row().prop(armature_id_store, "rigify_widgets_collection")
+        col.row().prop(armature_id_store, "rigify_force_widget_update")
+        col.row().prop(armature_id_store, "rigify_mirror_widgets")
+        col.separator()
+        col.row().prop(armature_id_store, "rigify_finalize_script", text="Run Script")
+
+
+class DATA_PT_rigify_samples(bpy.types.Panel):
+    bl_label = "Rigify Samples"
+    bl_space_type = 'PROPERTIES'
+    bl_region_type = 'WINDOW'
+    bl_context = "data"
+
+    @classmethod
+    def poll(cls, context):
+        obj = context.object
+        if not obj:
+            return False
+        return obj.type == 'ARMATURE' \
+            and obj.data.get("rig_id") is None \
+            and obj.mode == 'EDIT'
+
+    def draw(self, context):
+        layout = self.layout
+        layout.use_property_split = True
+        layout.use_property_decorate = False
+        obj = context.object
+        id_store = context.window_manager
+
+        # Build types list
+        build_type_list(context, id_store.rigify_types)
+
+        if id_store.rigify_active_type > len(id_store.rigify_types):
+            id_store.rigify_active_type = 0
+
+        # Rig type list
+        if len(feature_set_list.get_installed_list()) > 0:
             row = layout.row()
-            row.template_list("UI_UL_list", "rigify_types", id_store, "rigify_types", id_store, 'rigify_active_type')
+            row.prop(context.object.data, "active_feature_set")
+        row = layout.row()
+        row.template_list("UI_UL_list", "rigify_types", id_store, "rigify_types", id_store, 'rigify_active_type')
 
-            props = layout.operator("armature.metarig_sample_add", text="Add sample")
-            props.metarig_type = id_store.rigify_types[id_store.rigify_active_type].name
+        props = layout.operator("armature.metarig_sample_add", text="Add sample")
+        props.metarig_type = id_store.rigify_types[id_store.rigify_active_type].name
 
 
 class DATA_PT_rigify_layer_names(bpy.types.Panel):
@@ -791,8 +794,9 @@ class Generate(bpy.types.Operator):
         return is_metarig(context.object)
 
     def execute(self, context):
+        metarig = context.object
         try:
-            generate.generate_rig(context, context.object)
+            generate.generate_rig(context, metarig)
         except MetarigError as rig_exception:
             import traceback
             traceback.print_exc()
@@ -803,6 +807,8 @@ class Generate(bpy.types.Operator):
             traceback.print_exc()
 
             self.report({'ERROR'}, 'Generation has thrown an exception: ' + str(rig_exception))
+        else:
+            self.report({'INFO'}, 'Successfully generated: "' + metarig.data.rigify_target_rig.name + '"')
         finally:
             bpy.ops.object.mode_set(mode='OBJECT')
 
@@ -930,8 +936,10 @@ class VIEW3D_MT_rigify(bpy.types.Menu):
 
     def draw(self, context):
         layout = self.layout
+        obj = context.object
 
-        layout.operator(Generate.bl_idname, text="Generate")
+        text = "Re-Generate Rig" if obj.data.rigify_target_rig else "Generate Rig"
+        layout.operator(Generate.bl_idname, text=text)
 
         if context.mode == 'EDIT_ARMATURE':
             layout.separator()
@@ -1381,7 +1389,9 @@ classes = (
     DATA_MT_rigify_bone_groups_context_menu,
     DATA_PT_rigify_bone_groups,
     DATA_PT_rigify_layer_names,
-    DATA_PT_rigify_buttons,
+    DATA_PT_rigify_generate,
+    DATA_PT_rigify_generate_advanced,
+    DATA_PT_rigify_samples,
     BONE_PT_rigify_buttons,
     VIEW3D_PT_rigify_animation_tools,
     VIEW3D_PT_tools_rigify_dev,
diff --git a/rigify/utils/collections.py b/rigify/utils/collections.py
index a172b9849f4c9b83d26b9e3eea7f4acab45ba7f2..a19b9da1d9ac9668dba757a420ee52890ae1e3f5 100644
--- a/rigify/utils/collections.py
+++ b/rigify/utils/collections.py
@@ -19,9 +19,6 @@
 # <pep8 compliant>
 
 import bpy
-import math
-
-from .errors import MetarigError
 
 
 #=============================================
@@ -65,30 +62,32 @@ 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):
+def ensure_collection(context, collection_name, hidden=False) -> bpy.types.Collection:
+    """Check if a collection with a certain name exists.
+    If yes, return it, if not, create it in the scene root collection.
+    """
     view_layer = context.view_layer
-    layer_collection = bpy.context.layer_collection
-    collection = layer_collection.collection
+    active_layer_coll = bpy.context.layer_collection
+    active_collection = active_layer_coll.collection
 
-    widget_collection = bpy.data.collections.get(wgts_collection_name)
-    if not widget_collection:
-        # ------------------------------------------
-        # Create the widget collection
-        widget_collection = bpy.data.collections.new(wgts_collection_name)
-        widget_collection.hide_viewport = True
-        widget_collection.hide_render = True
+    collection = bpy.data.collections.get(collection_name)
+    if not collection:
+        # Create the collection
+        collection = bpy.data.collections.new(collection_name)
+        collection.hide_viewport = hidden
+        collection.hide_render = hidden
 
-        widget_layer_collection = None
+        layer_collection = None
     else:
-        widget_layer_collection = find_layer_collection_by_collection(view_layer.layer_collection, widget_collection)
+        layer_collection = find_layer_collection_by_collection(view_layer.layer_collection, collection)
 
-    if not widget_layer_collection:
-        # Add the widget collection to the tree
-        collection.children.link(widget_collection)
-        widget_layer_collection = [c for c in layer_collection.children if c.collection == widget_collection][0]
+    if not layer_collection:
+        # Let the new collection be a child of the active one.
+        active_collection.children.link(collection)
+        layer_collection = [c for c in active_layer_coll.children if c.collection == collection][0]
 
-        widget_layer_collection.exclude = True
+        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
+    # Make the new collection active.
+    view_layer.active_layer_collection = layer_collection
+    return collection
diff --git a/rigify/utils/widgets.py b/rigify/utils/widgets.py
index 3f0bf25224a67ec5cc15319c41b5533d8432d56e..b3715f807a3bb72c6fff0e90fec0a4c6e92d651a 100644
--- a/rigify/utils/widgets.py
+++ b/rigify/utils/widgets.py
@@ -27,7 +27,7 @@ from mathutils import Matrix, Vector, Euler
 from itertools import count
 
 from .errors import MetarigError
-from .collections import ensure_widget_collection
+from .collections import ensure_collection
 from .naming import change_name_side, get_name_side, Side
 
 WGT_PREFIX = "WGT-"  # Prefix for widget objects
@@ -79,7 +79,7 @@ def create_widget(rig, bone_name, bone_transform_name=None, *, widget_name=None,
     if generator:
         collection = generator.widget_collection
     else:
-        collection = ensure_widget_collection(bpy.context, 'WGTS_' + rig.name)
+        collection = ensure_collection(bpy.context, 'WGTS_' + rig.name, hidden=True)
 
     use_mirror = generator and generator.use_mirror_widgets