Example #1
0
    def execute(self, context):
        scene = context.scene

        if not ObjectService.object_is_basemesh(context.active_object):
            self.report({'ERROR'}, "Rigs can only be added to the base mesh")
            return {'FINISHED'}

        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'}
Example #2
0
    def draw(self, context):
        _LOG.enter()
        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)
    def draw(self, context):
        _LOG.enter()
        layout = self.layout
        scene = context.scene

        if not context.object:
            return

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

        basemesh = context.object

        _LOG.dump("target_dir", self.target_dir)
        for category in self.section["categories"]:
            self._draw_category(scene, layout, category, basemesh)
Example #4
0
    def execute(self, context):
        _LOG.enter()

        if context.object is None:
            self.report({'ERROR'}, "Must have a selected object")
            return {'FINISHED'}

        name = HUMAN_PRESETS_PROPERTIES.get_value("name",
                                                  entity_reference=context)
        if not name is None:
            name = str(name).strip()
        if name == "" or name is None:
            self.report({'ERROR'}, "A valid name must be given")
            return {'FINISHED'}
        if " " in str(name):
            self.report({'ERROR'},
                        "Human presets names should not contain spaces")
            return {'FINISHED'}

        confdir = LocationService.get_user_config()
        file_name = os.path.join(confdir, "human." + name + ".json")
        if os.path.exists(file_name):
            self.report({'ERROR'}, "Presets with that name already exist")
            return {'FINISHED'}

        basemesh = None
        if ObjectService.object_is_basemesh(context.object):
            basemesh = context.object
        else:
            basemesh = ObjectService.find_object_of_type_amongst_nearest_relatives(
                context.object, "Basemesh")

        if basemesh is None:
            self.report(
                {'ERROR'},
                "Could not find basemesh amongst relatives of selected object")
            return {'FINISHED'}

        HumanService.serialize_to_json_file(basemesh, file_name, True)
        self.report({'INFO'}, "Human saved as " + file_name)

        return {'FINISHED'}
Example #5
0
    def execute(self, context):
        scene = context.scene

        if not ObjectService.object_is_basemesh(context.active_object):
            self.report({'ERROR'}, "Rigs can only be added to the base mesh")
            return {'FINISHED'}

        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_rigify",
                                                      entity_reference=scene)
        generate = ADD_RIG_PROPERTIES.get_value("generate",
                                                entity_reference=scene)
        delete_after_generate = ADD_RIG_PROPERTIES.get_value(
            "delete_after_generate", entity_reference=scene)

        rigs_dir = LocationService.get_mpfb_data("rigs")
        rigify_dir = os.path.join(rigs_dir, "rigify")

        rig_file = os.path.join(rigify_dir, "rig.human.json")

        rig = Rig.from_json_file_and_basemesh(rig_file, basemesh)
        armature_object = rig.create_armature_and_fit_to_basemesh()
        armature_object.data.rigify_rig_basename = "Human.rigify"

        rigify_ui = dict()
        layer_file = os.path.join(rigify_dir, "rigify_layers.json")

        with open(layer_file, "r") as json_file:
            rigify_ui = json.load(json_file)

        bpy.ops.armature.rigify_add_bone_groups()
        bpy.ops.pose.rigify_layer_init()

        armature_object.data.rigify_colors_lock = rigify_ui[
            "rigify_colors_lock"]
        armature_object.data.rigify_selection_colors.select = rigify_ui[
            "selection_colors"]["select"]
        armature_object.data.rigify_selection_colors.active = rigify_ui[
            "selection_colors"]["active"]

        i = 0
        for color in armature_object.data.rigify_colors:
            col = rigify_ui["colors"][i]
            color.name = col["name"]
            color.normal = col["normal"]
            i = i + 1

        i = 0
        for rigify_layer in armature_object.data.layers:
            armature_object.data.layers[i] = rigify_ui["layers"][i]
            i = i + 1

        i = 0
        for rigify_layer in armature_object.data.rigify_layers:
            layer = rigify_ui["rigify_layers"][i]
            rigify_layer.name = layer["name"]
            rigify_layer.row = layer["row"]
            rigify_layer.selset = layer["selset"]
            rigify_layer.group = layer["group"]
            i = i + 1

        if not generate:
            basemesh.parent = armature_object

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

        if generate:
            bpy.ops.pose.rigify_generate()
            rigify_object = context.active_object
            rigify_object.show_in_front = True

            _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'}
Example #6
0
 def poll(cls, context):
     if context.active_object is not None:
         return ObjectService.object_is_basemesh(context.active_object)
     return False
    def fit_clothes_to_human(clothes, basemesh, mhclo=None):
        """Move clothes vertices so they fit the current shape of the base mesh."""

        if basemesh is None:
            raise ValueError('Cannot refit to None basemesh')

        if clothes is None:
            raise ValueError('Cannot refit to None clothes')

        if not ObjectService.object_is_basemesh(basemesh):
            raise ValueError('The provided object is not a basemesh')

        if mhclo is None:
            raise NotImplemented(
                "Searching for MHCLO info is not implemented yet, you must provide the MHCLO object"
            )

        # We cannot rely on the vertex position data directly, since it represent positions
        # as they are *before* targets are applied. We want the shape of the mesh *after*
        # targets are applied.
        #
        # We will therefore create a new shape key "from mix". This means it will have the
        # combined state of all current shape keys. Then we will use that shape key for
        # getting vertex positions.
        key_name = "temporary_fitting_key." + str(random.randrange(1000, 9999))
        basemesh.shape_key_add(name=key_name, from_mix=True)
        shape_key = basemesh.data.shape_keys.key_blocks[key_name]
        human_vertices = shape_key.data
        human_vertices_count = len(human_vertices)

        scale_factor = GeneralObjectProperties.get_value(
            "scale_factor", entity_reference=basemesh)
        if not scale_factor:
            scale_factor = 1.0

        # Fallback for if no scale is specified in mhclo
        z_size = y_size = x_size = scale_factor

        if mhclo.x_scale:
            if mhclo.x_scale[0] >= human_vertices_count or mhclo.x_scale[1] > human_vertices_count \
                or mhclo.y_scale[0] >= human_vertices_count or mhclo.y_scale[1] >= human_vertices_count \
                or mhclo.z_scale[0] >= human_vertices_count or mhclo.z_scale[1] >= human_vertices_count:
                _LOG.warn("Giving up refitting, not inside")
                raise ValueError("Cannot refit as we are not inside")

            x_size = abs(
                human_vertices[mhclo.x_scale[0]].co[0] -
                human_vertices[mhclo.x_scale[1]].co[0]) / mhclo.x_scale[2]
            y_size = abs(
                human_vertices[mhclo.y_scale[0]].co[2] -
                human_vertices[mhclo.y_scale[1]].co[2]) / mhclo.y_scale[2]
            z_size = abs(
                human_vertices[mhclo.z_scale[0]].co[1] -
                human_vertices[mhclo.z_scale[1]].co[1]) / mhclo.z_scale[2]

        _LOG.debug("x_scale, y_scale, z_scale",
                   (mhclo.x_scale, mhclo.y_scale, mhclo.z_scale))
        _LOG.debug("x_size, y_size, z_size", (x_size, y_size, z_size))

        clothes_vertices = mhclo.clothes.data.vertices

        _LOG.debug("About to try to match vertices: ", len(clothes_vertices))
        _LOG.dump("Verts", mhclo.verts)

        for clothes_vertex_number in range(len(clothes_vertices)):
            vertex_match_info = mhclo.verts[clothes_vertex_number]
            (human_vertex1, human_vertex2,
             human_vertex3) = vertex_match_info["verts"]

            # test if we inside mesh, if not, no chance
            #
            if human_vertex1 >= human_vertices_count or human_vertex2 > human_vertices_count or human_vertex3 >= human_vertices_count:
                continue

            offset = [
                vertex_match_info["offsets"][0] * x_size,
                vertex_match_info["offsets"][1] * z_size,
                vertex_match_info["offsets"][2] * y_size
            ]
            clothes_vertices[clothes_vertex_number].co = \
                vertex_match_info["weights"][0] * human_vertices[human_vertex1].co + \
                vertex_match_info["weights"][1] * human_vertices[human_vertex2].co + \
                vertex_match_info["weights"][2] * human_vertices[human_vertex3].co + \
                Vector(offset)

        # We need to take into account that the base mesh might be rigged. If it is, we'll want the rig position
        # rather than the basemesh position
        if basemesh.parent:
            clothes.location = (0.0, 0.0, 0.0)
            clothes.parent = basemesh.parent
        else:
            clothes.location = basemesh.location

        # As we are finished with the combined shape key we can now remove it
        basemesh.shape_key_remove(shape_key)
 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):

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

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

        scene = context.scene

        fit_to_body = ASSET_SETTINGS_PROPERTIES.get_value(
            "fit_to_body", entity_reference=scene)
        delete_group = ASSET_SETTINGS_PROPERTIES.get_value(
            "delete_group", entity_reference=scene)
        # TODO: specific_delete_group = ASSET_SETTINGS_PROPERTIES.get_value("specific_delete_group", entity_reference=scene)
        set_up_rigging = ASSET_SETTINGS_PROPERTIES.get_value(
            "set_up_rigging", entity_reference=scene)
        interpolate_weights = ASSET_SETTINGS_PROPERTIES.get_value(
            "interpolate_weights", entity_reference=scene)
        # TODO: makeclothes_metadata = ASSET_SETTINGS_PROPERTIES.get_value("makeclothes_metadata", entity_reference=scene)
        add_subdiv_modifier = ASSET_SETTINGS_PROPERTIES.get_value(
            "add_subdiv_modifier", entity_reference=scene)
        subdiv_levels = ASSET_SETTINGS_PROPERTIES.get_value(
            "subdiv_levels", entity_reference=scene)

        blender_object = context.active_object

        rig = None
        basemesh = None

        if blender_object and not blender_object is None:
            if ObjectService.object_is_basemesh(blender_object):
                basemesh = blender_object
            else:
                basemesh = ObjectService.find_object_of_type_amongst_nearest_relatives(
                    blender_object, "Basemesh")

            rig = ObjectService.find_object_of_type_amongst_nearest_relatives(
                blender_object, "Skeleton")

        if fit_to_body and basemesh is None:
            self.report(
                {'ERROR'},
                "Fit to body is enabled, but active object is not a base mesh")
            return {'FINISHED'}

        if delete_group and basemesh is None:
            self.report({
                'ERROR'
            }, "Set up delete group is enabled, but active object is not a base mesh"
                        )
            return {'FINISHED'}

        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'}
Example #10
0
    def execute(self, context):

        from mpfb.ui.loadclothes.loadclothespanel import LOAD_CLOTHES_PROPERTIES  # pylint: disable=C0415

        scene = context.scene

        object_type = LOAD_CLOTHES_PROPERTIES.get_value("object_type",
                                                        entity_reference=scene)
        material_type = LOAD_CLOTHES_PROPERTIES.get_value(
            "material_type", entity_reference=scene)
        fit_to_body = LOAD_CLOTHES_PROPERTIES.get_value("fit_to_body",
                                                        entity_reference=scene)
        delete_group = LOAD_CLOTHES_PROPERTIES.get_value(
            "delete_group", entity_reference=scene)
        specific_delete_group = LOAD_CLOTHES_PROPERTIES.get_value(
            "specific_delete_group", entity_reference=scene)
        set_up_rigging = LOAD_CLOTHES_PROPERTIES.get_value(
            "set_up_rigging", entity_reference=scene)
        interpolate_weights = LOAD_CLOTHES_PROPERTIES.get_value(
            "interpolate_weights", entity_reference=scene)
        makeclothes_metadata = LOAD_CLOTHES_PROPERTIES.get_value(
            "makeclothes_metadata", entity_reference=scene)

        blender_object = context.active_object

        rig = None
        basemesh = None

        if blender_object and not blender_object is None:
            if ObjectService.object_is_basemesh(blender_object):
                basemesh = blender_object
            else:
                basemesh = ObjectService.find_object_of_type_amongst_nearest_relatives(
                    blender_object, "Basemesh")

            rig = ObjectService.find_object_of_type_amongst_nearest_relatives(
                blender_object, "Skeleton")

        if fit_to_body and basemesh is None:
            self.report(
                {'ERROR'},
                "Fit to body is enabled, but active object is not a base mesh")
            return {'FINISHED'}

        if delete_group and basemesh is None:
            self.report({
                'ERROR'
            }, "Set up delete group is enabled, but active object is not a base mesh"
                        )
            return {'FINISHED'}

        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'}

        mhclo = Mhclo()
        mhclo.load(self.filepath)  # pylint: disable=E1101
        clothes = mhclo.load_mesh(context)

        if not clothes or clothes is None:
            self.report({'ERROR'}, "failed to import the clothes mesh")
            return {'FINISHED'}

        GeneralObjectProperties.set_value("object_type",
                                          object_type,
                                          entity_reference=clothes)
        bpy.ops.object.shade_smooth()

        if not material_type == "PRINCIPLED":
            MaterialService.delete_all_materials(clothes)

        if material_type == "MAKESKIN" and not mhclo.material is None:
            makeskin_material = MakeSkinMaterial()
            makeskin_material.populate_from_mhmat(mhclo.material)
            name = os.path.basename(mhclo.material)
            blender_material = MaterialService.create_empty_material(
                name, clothes)
            makeskin_material.apply_node_tree(blender_material)

        if fit_to_body:
            ClothesService.fit_clothes_to_human(clothes, basemesh, mhclo)
            mhclo.set_scalings(context, basemesh)

        delete_name = "Delete"
        if delete_group:
            if specific_delete_group:
                delete_name = str(os.path.basename(self.filepath))  # pylint: disable=E1101
                delete_name = delete_name.replace(".mhclo", "")
                delete_name = delete_name.replace(".MHCLO", "")
                delete_name = delete_name.replace(" ", "_")
                delete_name = "Delete." + delete_name
            ClothesService.update_delete_group(mhclo,
                                               basemesh,
                                               replace_delete_group=False,
                                               delete_group_name=delete_name)

        if set_up_rigging:
            clothes.location = (0.0, 0.0, 0.0)
            clothes.parent = rig
            modifier = clothes.modifiers.new("Armature", 'ARMATURE')
            modifier.object = rig
            if interpolate_weights:
                ClothesService.interpolate_weights(basemesh, clothes, rig,
                                                   mhclo)

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

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

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

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

        scene = context.scene

        object_type = self.object_type
        material_type = "MAKESKIN" # TODO: some kind of operator argument
        fit_to_body = ASSET_SETTINGS_PROPERTIES.get_value("fit_to_body", entity_reference=scene)
        delete_group = ASSET_SETTINGS_PROPERTIES.get_value("delete_group", entity_reference=scene)
        specific_delete_group = ASSET_SETTINGS_PROPERTIES.get_value("specific_delete_group", entity_reference=scene)
        set_up_rigging = ASSET_SETTINGS_PROPERTIES.get_value("set_up_rigging", entity_reference=scene)
        interpolate_weights = ASSET_SETTINGS_PROPERTIES.get_value("interpolate_weights", entity_reference=scene)
        makeclothes_metadata = ASSET_SETTINGS_PROPERTIES.get_value("makeclothes_metadata", entity_reference=scene)
        add_subdiv_modifier = ASSET_SETTINGS_PROPERTIES.get_value("add_subdiv_modifier", entity_reference=scene)
        subdiv_levels = ASSET_SETTINGS_PROPERTIES.get_value("subdiv_levels", entity_reference=scene)
        mask_base_mesh = ASSET_SETTINGS_PROPERTIES.get_value("mask_base_mesh", entity_reference=scene)

        blender_object = context.active_object

        rig = None
        basemesh = None

        if blender_object and not blender_object is None:
            if ObjectService.object_is_basemesh(blender_object):
                basemesh = blender_object
            else:
                basemesh = ObjectService.find_object_of_type_amongst_nearest_relatives(blender_object, "Basemesh")

            rig = ObjectService.find_object_of_type_amongst_nearest_relatives(blender_object, "Skeleton")

        if fit_to_body and basemesh is None:
            self.report({'ERROR'}, "Fit to body is enabled, but active object is not a base mesh")
            return {'FINISHED'}

        if delete_group and basemesh is None:
            self.report({'ERROR'}, "Set up delete group is enabled, but active object is not a base mesh")
            return {'FINISHED'}

        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'}

        mhclo = Mhclo()
        mhclo.load(self.filepath) # pylint: disable=E1101
        clothes = mhclo.load_mesh(context)

        if not clothes or clothes is None:
            self.report({'ERROR'}, "failed to import the proxy")
            return {'FINISHED'}

        asset_dir = os.path.basename(os.path.dirname(os.path.realpath(self.filepath)))
        asset_source = asset_dir + "/" + os.path.basename(self.filepath)

        GeneralObjectProperties.set_value("object_type", "Proxymeshes", entity_reference=clothes)
        GeneralObjectProperties.set_value("asset_source", asset_source, entity_reference=clothes)

        bpy.ops.object.shade_smooth()

        if not material_type == "PRINCIPLED":
            MaterialService.delete_all_materials(clothes)

        if material_type == "MAKESKIN" and not mhclo.material is None:
            makeskin_material = MakeSkinMaterial()
            makeskin_material.populate_from_mhmat(mhclo.material)
            name = os.path.basename(mhclo.material)
            blender_material = MaterialService.create_empty_material(name, clothes)
            makeskin_material.apply_node_tree(blender_material)

        if fit_to_body:
            ClothesService.fit_clothes_to_human(clothes, basemesh, mhclo)
            mhclo.set_scalings(context, basemesh)

        if set_up_rigging:
            clothes.location = (0.0, 0.0, 0.0)
            clothes.parent = rig
            modifier = clothes.modifiers.new("Armature", 'ARMATURE')
            modifier.object = rig
            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'}