Example #1
0
from mpfb import ClassManager

_LOG = LogService.get_logger("makeclothes.markclothes")


class MPFB_OT_MarkClothesOperator(bpy.types.Operator):
    """Set mesh type to clothes"""
    bl_idname = "mpfb.mark_makeclothes_clothes"
    bl_label = "Mark as clothes"
    bl_options = {'REGISTER'}

    @classmethod
    def poll(cls, context):
        if context.active_object is not None:
            return context.active_object.type == "MESH"
        return False

    def execute(self, context):

        blender_object = context.active_object
        scene = context.scene

        from mpfb.ui.makeclothes.makeclothespanel import MAKECLOTHES_PROPERTIES  # pylint: disable=C0415
        from mpfb.ui.makeclothes import MakeClothesObjectProperties  # pylint: disable=C0415

        self.report({'INFO'}, "Mesh type was set to clothes")
        return {'FINISHED'}


ClassManager.add_class(MPFB_OT_MarkClothesOperator)
Example #2
0
"""Operator for opening web browser"""

import webbrowser, bpy
from bpy.props import StringProperty
from mpfb.services.logservice import LogService
from mpfb import ClassManager

_LOG = LogService.get_logger("webresources.webresource")


class MPFB_OT_Web_Resource_Operator(bpy.types.Operator):
    """Open web browser"""
    bl_idname = "mpfb.web_resource"
    bl_label = "Open"
    bl_options = {'REGISTER'}

    url: StringProperty(name="url", description="Address to open", default="")

    def execute(self, context):
        webbrowser.open(self.url)
        return {'FINISHED'}


ClassManager.add_class(MPFB_OT_Web_Resource_Operator)
Example #3
0
    def invoke(self, context, event):
        blender_object = context.active_object
        name = MakeTargetObjectProperties.get_value(
            "name", entity_reference=blender_object)
        self.filepath = bpy.path.clean_name(name, replace="-") + ".target"
        return super().invoke(context, event)

    def execute(self, context):

        blender_object = context.active_object
        target_string = Path(self.filepath).read_text()

        TargetService.target_string_to_shape_key(target_string,
                                                 "PrimaryTarget",
                                                 blender_object)

        # This might look strange, but it is to ensure the name attribute of the object
        # is not still null if left at its default
        name = MakeTargetObjectProperties.get_value(
            "name", entity_reference=blender_object)
        MakeTargetObjectProperties.set_value("name",
                                             name,
                                             entity_reference=blender_object)

        self.report({'INFO'}, "Target was imported as shape key")
        return {'FINISHED'}


ClassManager.add_class(MPFB_OT_ImportTargetOperator)
Example #4
0
        blender_object = context.active_object

        file_name = bpy.path.abspath(self.filepath)

        if not MaterialService.has_materials(blender_object):
            self.report({'ERROR'}, "Object does not have a material")
            return {'FINISHED'}

        material = MakeSkinMaterial()
        material.populate_from_object(blender_object)

        mhmat_string = material.as_mhmat()
        _LOG.dump("material", mhmat_string)

        image_file_error = material.check_that_all_textures_are_saved(
            blender_object)
        if not image_file_error is None:
            self.report({'ERROR'}, image_file_error)
            return {'FINISHED'}

        # TODO: copy normalized images

        with open(file_name, "w") as mhmat:
            mhmat.write(mhmat_string)

        self.report({'INFO'}, "The MHMAT file was written as " + file_name)
        return {'FINISHED'}


ClassManager.add_class(MPFB_OT_WriteMaterialOperator)
    def execute(self, context):
        obj = context.active_object
        scn = context.scene

        from mpfb.ui.makeskin.makeskinpanel import MAKESKIN_PROPERTIES

        if MaterialService.has_materials(obj):
            if not MAKESKIN_PROPERTIES.get_value("overwrite",
                                                 entity_reference=scn):
                self.report({
                    'ERROR'
                }, "A material for this object already exists, change 'replace' option in common settings to overwrite material"
                            )
                return {'FINISHED'}
            else:
                while len(obj.data.materials) > 0:
                    obj.data.materials.pop(index=0)

        material = MaterialService.create_empty_material(
            "makeskinmaterial", obj)

        mhmat = MakeSkinMaterial()
        mhmat.populate_from_mhmat(self.filepath)
        mhmat.apply_node_tree(material)

        self.report({'INFO'}, "Material imported")
        return {'FINISHED'}


ClassManager.add_class(MPFB_OT_ImportMaterialOperator)
                                 description="Set target value",
                                 max=1.0,
                                 min=_min_val)
            setattr(bpy.types.Scene, _right_name, prop)
            _LOG.debug("property", prop)
        else:
            prop = FloatProperty(name=_unsided_name,
                                 get=_get_wrapper_unsided,
                                 set=_set_wrapper_unsided,
                                 description="Set target value",
                                 max=1.0,
                                 min=_min_val)
            setattr(bpy.types.Scene, _unsided_name, prop)
            _LOG.debug("property", prop)

        _i = _i + 1

    definition = {
        "bl_label": _section["label"],
        "target_dir": os.path.join(_TARGETS_DIR, name),
        "section": _section,
        "section_name": name
    }

    sub_panel = type("MPFB_PT_Model_Sub_Panel_" + name,
                     (_Abstract_Model_Panel, ), definition)

    _LOG.debug("sub_panel", sub_panel)

    ClassManager.add_class(sub_panel)
Example #7
0
        layout = self.layout
        scene = context.scene

        if not context.object:
            return

        if not ObjectService.object_is_basemesh(context.object):
            return

        basemesh = context.object

        for category_name in _MACROTARGETS.keys():
            targets = _MACROTARGETS[category_name]
            self._draw_category(scene, layout, category_name, targets, basemesh)

ClassManager.add_class(MPFB_PT_Macro_Sub_Panel)

_PROPS_DIR = os.path.join(LocationService.get_mpfb_root("entities"), "objectproperties", "humanproperties")

def _general_set_target_value(name, value):
    _LOG.trace("_general_set_target_value", (name, value))
    basemesh = bpy.context.object
    HumanObjectProperties.set_value(name, value, entity_reference=basemesh)
    TargetService.reapply_macro_details(basemesh)
    #===========================================================================
    # macro_info = TargetService.get_macro_info_dict_from_basemesh(basemesh)
    # _LOG.debug("macro_info", macro_info)
    # target_stack = TargetService.calculate_target_stack_from_macro_info_dict(macro_info)
    # _LOG.debug("target_stack", target_stack)
    #===========================================================================
        if scale_factor == "CENTIMETER":
            scale = 10.0

        fullname = "human." + name + ".json"
        filename = LocationService.get_user_config(fullname)

        _LOG.debug("filename", filename)

        basemesh = HumanService.deserialize_from_json_file(filename,
                                                           mask_helpers=mask_helpers,
                                                           detailed_helpers=detailed_helpers,
                                                           extra_vertex_groups=extra_vertex_groups,
                                                           feet_on_ground=True,
                                                           scale=scale)

        _LOG.debug("Basemesh", basemesh)

        bpy.ops.object.select_all(action='DESELECT')
        bpy.context.view_layer.objects.active = basemesh
        basemesh.select_set(True)

        _LOG.time("Human created in")

        self.report({'INFO'}, "Human created")
        return {'FINISHED'}


ClassManager.add_class(MPFB_OT_HumanFromPresetsOperator)

Example #9
0
class MPFB_OT_CreateTargetOperator(bpy.types.Operator):
    """Create primary target"""
    bl_idname = "mpfb.create_maketarget_target"
    bl_label = "Create target"
    bl_options = {'REGISTER', 'UNDO'}

    @classmethod
    def poll(cls, context):
        if not ObjectService.object_is_basemesh(context.active_object):
            return False
        return not context.active_object.data.shape_keys

    def execute(self, context):
        blender_object = context.active_object
        TargetService.create_shape_key(blender_object, "PrimaryTarget")

        # This might look strange, but it is to ensure the name attribute of the object
        # is not still null if left at its default
        name = MakeTargetObjectProperties.get_value(
            "name", entity_reference=blender_object)
        MakeTargetObjectProperties.set_value("name",
                                             name,
                                             entity_reference=blender_object)

        self.report({'INFO'}, "Primary target created")
        return {'FINISHED'}


ClassManager.add_class(MPFB_OT_CreateTargetOperator)
Example #10
0
            basemesh = HumanService.create_human(
                mask_helpers=mask_helpers,
                detailed_helpers=detailed_helpers,
                extra_vertex_groups=extra_vertex_groups,
                feet_on_ground=True,
                scale=scale,
                macro_detail_dict=macro_details)
            self.report({
                'INFO'
            }, "Human created. You can adjust the phenotype values on the modeling panel."
                        )
        else:
            basemesh = HumanService.create_human(
                mask_helpers=mask_helpers,
                detailed_helpers=detailed_helpers,
                extra_vertex_groups=extra_vertex_groups,
                feet_on_ground=True,
                scale=scale)
            self.report({'INFO'}, "Human created.")

        _LOG.debug("Basemesh", basemesh)

        bpy.ops.object.select_all(action='DESELECT')
        bpy.context.view_layer.objects.active = basemesh
        basemesh.select_set(True)

        return {'FINISHED'}


ClassManager.add_class(MPFB_OT_CreateHumanOperator)
Example #11
0
from mpfb import ClassManager

_LOG = LogService.get_logger("makeclothes.extractclothes")


class MPFB_OT_ExtractClothesOperator(bpy.types.Operator):
    """Extract clothes from base mesh helpers"""
    bl_idname = "mpfb.extract_makeclothes_clothes"
    bl_label = "Extract clothes"
    bl_options = {'REGISTER'}

    @classmethod
    def poll(cls, context):
        if context.active_object is not None:
            return context.active_object.type == "MESH"
        return False

    def execute(self, context):

        blender_object = context.active_object
        scene = context.scene

        from mpfb.ui.makeclothes.makeclothespanel import MAKECLOTHES_PROPERTIES  # pylint: disable=C0415
        from mpfb.ui.makeclothes import MakeClothesObjectProperties  # pylint: disable=C0415

        self.report({'INFO'}, "Clothes mesh was created")
        return {'FINISHED'}


ClassManager.add_class(MPFB_OT_ExtractClothesOperator)
Example #12
0
    @classmethod
    def poll(cls, context):
        return context.active_object is not None

    def invoke(self, context, event):
        # TODO: support blender materials
        #=======================================================================
        # if not self.filepath:
        #     blend_filepath = context.active_object.MhMsName
        #     # just in case ... ;)
        #     if not blend_filepath:
        #         blend_filepath = "untitled"
        #     self.filepath = blend_filepath + self.filename_ext
        #=======================================================================

        context.window_manager.fileselect_add(self)
        return {'RUNNING_MODAL'}

    def execute(self, context):

        blender_object = context.active_object

        file_name = bpy.path.abspath(self.filepath)

        self.report({'INFO'}, "The MHCLO file was written as " + file_name)
        return {'FINISHED'}


ClassManager.add_class(MPFB_OT_WriteClothesOperator)
Example #13
0
    def execute(self, context):

        _LOG.debug("filepath", self.filepath)

        from mpfb.ui.assetlibrary.assetsettingspanel import ASSET_SETTINGS_PROPERTIES  # pylint: disable=C0415

        scene = context.scene

        skin_type = ASSET_SETTINGS_PROPERTIES.get_value("skin_type",
                                                        entity_reference=scene)
        material_instances = ASSET_SETTINGS_PROPERTIES.get_value(
            "material_instances", entity_reference=scene)

        blender_object = context.active_object
        basemesh = ObjectService.find_object_of_type_amongst_nearest_relatives(
            blender_object, "Basemesh")
        bodyproxy = ObjectService.find_object_of_type_amongst_nearest_relatives(
            blender_object, "Proxymeshes")

        HumanService.set_character_skin(self.filepath,
                                        basemesh,
                                        bodyproxy=bodyproxy,
                                        skin_type=skin_type,
                                        material_instances=material_instances)

        self.report({'INFO'}, "Skin was loaded")
        return {'FINISHED'}


ClassManager.add_class(MPFB_OT_Load_Library_Skin_Operator)
Example #14
0

class MPFB_OT_PrintTargetOperator(bpy.types.Operator):
    """Dump target data to console"""
    bl_idname = "mpfb.print_maketarget_target"
    bl_label = "Print target"
    bl_options = {'REGISTER'}

    @classmethod
    def poll(cls, context):
        if not ObjectService.object_is_basemesh(context.active_object):
            return False
        if context.active_object.data.shape_keys:
            return True
        return False

    def execute(self, context):
        blender_object = context.active_object
        info = TargetService.get_shape_key_as_dict(blender_object,
                                                   "PrimaryTarget")

        _LOG.dump("Shape key", info)

        print(TargetService.shape_key_info_as_target_string(info))

        self.report({'INFO'}, "Target printed to console")
        return {'FINISHED'}


ClassManager.add_class(MPFB_OT_PrintTargetOperator)
Example #15
0
        basemesh = context.active_object

        from mpfb.ui.addrig.addrigpanel import ADD_RIG_PROPERTIES # pylint: disable=C0415

        import_weights = ADD_RIG_PROPERTIES.get_value("import_weights", entity_reference=scene)
        standard_rig = ADD_RIG_PROPERTIES.get_value("standard_rig", entity_reference=scene)

        rigs_dir = LocationService.get_mpfb_data("rigs")
        standard_dir = os.path.join(rigs_dir, "standard")

        rig_file = os.path.join(standard_dir, "rig." + standard_rig + ".json")

        rig = Rig.from_json_file_and_basemesh(rig_file, basemesh)
        armature_object = rig.create_armature_and_fit_to_basemesh()

        basemesh.parent = armature_object

        if import_weights:
            weights_file = os.path.join(standard_dir, "weights." + standard_rig + ".json")
            weights = dict()
            with open(weights_file, 'r') as json_file:
                weights = json.load(json_file)
            RigService.apply_weights(armature_object, basemesh, weights)

        self.report({'INFO'}, "A rig was added")
        return {'FINISHED'}


ClassManager.add_class(MPFB_OT_AddStandardRigOperator)

            if interpolate_weights:
                ClothesService.interpolate_weights(basemesh, clothes, rig, mhclo)

        if add_subdiv_modifier:
            modifier = clothes.modifiers.new("Subdivision", 'SUBSURF')
            modifier.levels = 0
            modifier.render_levels = subdiv_levels

        if mask_base_mesh:
            modifier = basemesh.modifiers.new("Hide base mesh", 'MASK')
            modifier.vertex_group = "body"
            modifier.invert_vertex_group = True

        #if makeclothes_metadata:
        #    ClothesService.set_makeclothes_object_properties_from_mhclo(clothes, mhclo, delete_group_name=delete_name)

        _LOG.debug("clothes, uuid", (clothes, mhclo.uuid))
        if clothes and mhclo.uuid:
            GeneralObjectProperties.set_value("uuid", mhclo.uuid, entity_reference=clothes)
            _LOG.debug("Has extra vgroups", mhclo.uuid in ALL_EXTRA_GROUPS)
            if mhclo.uuid in ALL_EXTRA_GROUPS:
                for vgroup_name in ALL_EXTRA_GROUPS[mhclo.uuid].keys():
                    _LOG.debug("Will create vgroup", vgroup_name)
                    vgroup = clothes.vertex_groups.new(name=vgroup_name)
                    vgroup.add(ALL_EXTRA_GROUPS[mhclo.uuid][vgroup_name], 1.0, 'ADD')

        self.report({'INFO'}, "Proxy was loaded")
        return {'FINISHED'}

ClassManager.add_class(MPFB_OT_Load_Library_Proxy_Operator)
Example #17
0
        return box

    def _refit(self, scene, layout):
        box = self._create_box(layout, "Refit")
        #=======================================================================
        # NEW_HUMAN_PROPERTIES.draw_properties(scene, box, [
        #     "scale_factor",
        #     "detailed_helpers",
        #     "extra_vertex_groups",
        #     "mask_helpers"
        #     ])
        # box.operator('mpfb.create_human')
        #=======================================================================

    def draw(self, context):
        _LOG.enter()
        layout = self.layout
        scene = context.scene

        self._refit(scene, layout)

    @classmethod
    def poll(cls, context):
        return ObjectService.object_is_basemesh(context.active_object)


ClassManager.add_class(MPFB_PT_Model_Panel)

from ._macrosubpanel import MPFB_PT_Macro_Sub_Panel
from ._modelsubpanels import *
Example #18
0
    bl_label = "Load pack from zip file"
    bl_options = {'REGISTER'}

    filter_glob: StringProperty(default='*.zip', options={'HIDDEN'})

    def execute(self, context):

        if not self.filepath:
            self.report({'ERROR'}, "Must select a file")
            return {'FINISHED'}

        if not os.path.exists(self.filepath):
            self.report({'ERROR'}, "File does not exist?")
            return {'FINISHED'}

        data_dir = LocationService.get_user_data()

        with zipfile.ZipFile(self.filepath, 'r') as zip_ref:
            zip_ref.extractall(data_dir)

        AssetService.update_all_asset_lists()

        self.report({
            'INFO'
        }, "Assets should now be available. If they are not visible, then restart Blender."
                    )
        return {'FINISHED'}


ClassManager.add_class(MPFB_OT_Load_Pack_Operator)
Example #19
0
            "mask_helpers"
        ])
        box.operator('mpfb.create_human')

    def _phenotype(self, scene, layout):
        box = self._create_box(layout, "Phenotype")
        NEW_HUMAN_PROPERTIES.draw_properties(scene, box, [
            "phenotype_gender", "phenotype_age", "phenotype_muscle",
            "phenotype_weight", "phenotype_height", "phenotype_race",
            "add_phenotype", "phenotype_influence"
        ])

    def _breast(self, scene, layout):
        box = self._create_box(layout, "Breast")
        NEW_HUMAN_PROPERTIES.draw_properties(scene, box, [
            "phenotype_breastsize", "phenotype_breastfirmness", "add_breast",
            "breast_influence"
        ])

    def draw(self, context):
        _LOG.enter()
        layout = self.layout
        scene = context.scene

        self._phenotype(scene, layout)
        self._breast(scene, layout)
        self._create(scene, layout)


ClassManager.add_class(MPFB_PT_NewHuman_Panel)
        if interpolate_weights and basemesh is None:
            self.report({
                'ERROR'
            }, "interpolate weights is enabled, but active object is not a base mesh"
                        )
            return {'FINISHED'}

        if set_up_rigging and rig is None:
            self.report({
                'ERROR'
            }, "set up rigging is enabled, but could not find a rig to attach to"
                        )
            return {'FINISHED'}

        if not add_subdiv_modifier:
            subdiv_levels = 0

        _LOG.debug("Will call add_mhclo_asset: (asset_type, material_type)",
                   (self.object_type, self.material_type))
        HumanService.add_mhclo_asset(self.filepath,
                                     basemesh,
                                     asset_type=self.object_type,
                                     subdiv_levels=subdiv_levels,
                                     material_type=self.material_type)

        self.report({'INFO'}, "Clothes were loaded")
        return {'FINISHED'}


ClassManager.add_class(MPFB_OT_Load_Library_Clothes_Operator)
Example #21
0
class MPFB_PT_Add_Rig_Panel(Abstract_Panel):
    """Functionality for adding/setting rig"""

    bl_label = "Add rig"
    bl_category = UiService.get_value("MODELCATEGORY")
    bl_parent_id = "MPFB_PT_Rig_Panel"

    def _standard_rig(self, scene, layout):
        box = self.create_box(layout, "Add standard rig")
        props = ["standard_rig", "import_weights"]
        ADD_RIG_PROPERTIES.draw_properties(scene, box, props)
        box.operator('mpfb.add_standard_rig')

    def _rigify_rig(self, scene, layout):
        box = self.create_box(layout, "Add rigify rig")
        props = ["import_weights_rigify", "delete_after_generate", "generate"]
        ADD_RIG_PROPERTIES.draw_properties(scene, box, props)
        box.operator('mpfb.add_rigify_rig')
        box.operator('mpfb.generate_rigify_rig')

    def draw(self, context):
        _LOG.enter()
        layout = self.layout
        scene = context.scene
        self._standard_rig(scene, layout)
        self._rigify_rig(scene, layout)


ClassManager.add_class(MPFB_PT_Add_Rig_Panel)
from mpfb.services.objectservice import ObjectService
from mpfb.services.targetservice import TargetService
from mpfb import ClassManager

_LOG = LogService.get_logger("maketarget.symmetrizeleft")

class MPFB_OT_SymmetrizeLeftOperator(bpy.types.Operator):
    """Symmetrize by taking the right side of the model and copy it mirrored to the left side"""
    bl_idname = "mpfb.symmetrize_maketarget_left"
    bl_label = "Copy -x to +x"
    bl_options = {'REGISTER', 'UNDO'}

    @classmethod
    def poll(cls, context):
        if not ObjectService.object_is_basemesh(context.active_object):
            return False
        if context.active_object.data.shape_keys:
            return True
        return False

    def execute(self, context):

        blender_object = context.active_object
        TargetService.symmetrize_shape_key(blender_object, "PrimaryTarget", False)

        self.report({'INFO'}, "Target symmetrized")
        return {'FINISHED'}


ClassManager.add_class(MPFB_OT_SymmetrizeLeftOperator)
Example #23
0
        box.operator('mpfb.import_makeskin_material')

    def _save_material(self, blender_object, layout):
        box = self._create_box(layout, "Write material", "MATERIAL_DATA")
        props = [
            "name", "description", "tag", "license", "author", "homepage",
            "backface_culling", "cast_shadows", "receive_shadows",
            "alpha_to_coverage", "shadeless", "wireframe", "transparent",
            "depthless", "sss_enable", "auto_blend", "textures",
            "use_litsphere", "litsphere"
        ]
        MakeSkinObjectProperties.draw_properties(blender_object, box, props)
        box.operator('mpfb.write_makeskin_material')

    def draw(self, context):
        _LOG.enter()
        layout = self.layout
        scene = context.scene

        blender_object = context.active_object
        if blender_object is None:
            return

        if blender_object.type == "MESH":
            self._create_material(scene, layout)
            self._import_material(layout)
            self._save_material(blender_object, layout)


ClassManager.add_class(MPFB_PT_MakeSkin_Panel)
Example #24
0
        box.operator('mpfb.symmetrize_maketarget_left')
        box.operator('mpfb.symmetrize_maketarget_right')

    def _debug_target(self, scene, layout):
        box = self._create_box(layout, "Debug", "TOOL_SETTINGS")
        box.operator('mpfb.print_maketarget_target')

    def draw(self, context):
        _LOG.enter()
        layout = self.layout
        scene = context.scene

        blender_object = context.active_object
        if blender_object is None:
            return

        object_type = GeneralObjectProperties.get_value("object_type", entity_reference=blender_object)

        if object_type == "Basemesh":
            if not blender_object.data.shape_keys:
                self._initialize_target(blender_object, layout)
            else:
                self._save_target(scene, layout)
                self._symmetrize_target(scene, layout)
                self._debug_target(scene, layout)


ClassManager.add_class(MPFB_PT_MakeTarget_Panel)


        box.operator('mpfb.mark_makeclothes_clothes')

    def _write_clothes(self, blender_object, scene, layout):
        box = self._create_box(layout, "Write clothes", "MATERIAL_DATA")

        props = ["overwrite"]
        MAKECLOTHES_PROPERTIES.draw_properties(scene, box, props)

        props = ["name", "description", "tag", "license", "author", "homepage"]
        MakeClothesObjectProperties.draw_properties(blender_object, box, props)

        box.operator('mpfb.write_makeclothes_clothes')

    def draw(self, context):
        _LOG.enter()
        layout = self.layout
        scene = context.scene

        blender_object = context.active_object

        #self._setup_clothes(scene, layout)

        if blender_object is None:
            return

        #if blender_object.type == "MESH":
        #    self._write_clothes(blender_object, scene, layout)


ClassManager.add_class(MPFB_PT_MakeClothes_Panel)
        for child in ObjectService.get_list_of_children(armature_object):

            child.parent = rigify_object

            for bone in armature_object.data.bones:
                name = bone.name
                if name in child.vertex_groups and not "teeth" in name:
                    vertex_group = child.vertex_groups.get(name)
                    vertex_group.name = "DEF-" + name

            for modifier in child.modifiers:
                if modifier.type == 'ARMATURE':
                    modifier.object = rigify_object

        if delete_after_generate:
            objs = bpy.data.objects
            objs.remove(objs[armature_object.name], do_unlink=True)

        bpy.ops.object.mode_set(mode='EDIT', toggle=False)

        teethb = RigService.find_edit_bone_by_name("teeth.B", rigify_object)
        teethb.use_deform = True

        bpy.ops.object.mode_set(mode='OBJECT', toggle=False)

        self.report({'INFO'}, "A rig was generated")
        return {'FINISHED'}


ClassManager.add_class(MPFB_OT_GenerateRigifyRigOperator)
Example #27
0
            _LOG.debug("rigify", rigify_object)
            basemesh.parent = rigify_object

            for bone in armature_object.data.bones:
                name = bone.name
                if name in basemesh.vertex_groups and not "teeth" in name:
                    vertex_group = basemesh.vertex_groups.get(name)
                    vertex_group.name = "DEF-" + name

            for modifier in basemesh.modifiers:
                if modifier.type == 'ARMATURE':
                    modifier.object = rigify_object

            if delete_after_generate:
                objs = bpy.data.objects
                objs.remove(objs[armature_object.name], do_unlink=True)

            bpy.ops.object.mode_set(mode='EDIT', toggle=False)

            teethb = RigService.find_edit_bone_by_name("teeth.B",
                                                       rigify_object)
            teethb.use_deform = True

            bpy.ops.object.mode_set(mode='OBJECT', toggle=False)

        self.report({'INFO'}, "A rig was added")
        return {'FINISHED'}


ClassManager.add_class(MPFB_OT_AddRigifyRigOperator)
class MPFB_PT_From_Presets_Panel(Abstract_Panel):
    """Create human from preset main panel."""

    bl_label = "From presets"
    bl_space_type = "VIEW_3D"
    bl_region_type = "UI"
    bl_category = UiService.get_value("MODELCATEGORY")
    bl_options = {'DEFAULT_CLOSED'}
    bl_parent_id = "MPFB_PT_New_Panel"

    def _create(self, scene, layout):
        PRESETS_HUMAN_PROPERTIES.draw_properties(scene, layout, [
            "available_presets",
            "scale_factor",
            "detailed_helpers",
            "extra_vertex_groups",
            "mask_helpers"
            ])
        layout.operator('mpfb.human_from_presets')

    def draw(self, context):
        _LOG.enter()
        layout = self.layout
        scene = context.scene
        self._create(scene, layout)


ClassManager.add_class(MPFB_PT_From_Presets_Panel)