Пример #1
0
    def create_armature_and_fit_to_basemesh(self):
        """Use the information in the object to construct an armature and adjust it to fit the base mesh."""

        #self.move_basemesh_if_needed()

        bpy.ops.object.armature_add(location=self.basemesh.location)
        self.armature_object = bpy.context.object

        scale_factor = GeneralObjectProperties.get_value("scale_factor", entity_reference=self.basemesh)
        GeneralObjectProperties.set_value("scale_factor", scale_factor, entity_reference=self.armature_object)
        GeneralObjectProperties.set_value("object_type", "Skeleton", entity_reference=self.armature_object)

        self.armature_object.show_in_front = True
        self.armature_object.data.display_type = 'WIRE'

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

        for bone in self.armature_object.data.edit_bones:
            self.armature_object.data.edit_bones.remove(bone)

        bpy.ops.object.mode_set(mode='OBJECT', toggle=False) # To commit removal of bones

        self.create_bones()
        self.update_edit_bone_metadata()
        self.rigify_metadata()

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

        modifier = self.basemesh.modifiers.new("Armature", 'ARMATURE')
        modifier.object = self.armature_object
        while self.basemesh.modifiers.find(modifier.name) != 0:
            bpy.ops.object.modifier_move_up({'object': self.basemesh}, modifier=modifier.name)

        return self.armature_object
Пример #2
0
 def load_base_mesh(context=None, scale_factor=1.0, load_vertex_groups=True, exclude_vertex_groups=None):
     objsdir = LocationService.get_mpfb_data("3dobjs")
     filepath = os.path.join(objsdir, "base.obj")
     basemesh = ObjectService.load_wavefront_file(filepath, context)
     basemesh.name = "Human"
     bpy.ops.object.shade_smooth()
     bpy.ops.transform.resize(value=(scale_factor, scale_factor, scale_factor))
     bpy.ops.object.transform_apply(scale=True)
     GeneralObjectProperties.set_value("object_type", "Basemesh", entity_reference=basemesh)
     GeneralObjectProperties.set_value("scale_factor", scale_factor, entity_reference=basemesh)
     if load_vertex_groups:
         groups = ObjectService.get_base_mesh_vertex_group_definition()
         ObjectService.assign_vertex_groups(basemesh, groups, exclude_vertex_groups)
     return basemesh
Пример #3
0
    def _check_add_proxy(human_info, basemesh, subdiv_levels=1):
        if not "proxy" in human_info:
            _LOG.warn("Did not find proxy key in human_info")
            return
        if human_info["proxy"] is None or not human_info["proxy"]:
            _LOG.debug("No proxy was specified")
            return

        _LOG.debug("A proxy was specified", human_info["proxy"])
        asset_absolute_path = AssetService.find_asset_absolute_path(human_info["proxy"], asset_subdir="proxymeshes")
        _LOG.debug("Asset absolute path", asset_absolute_path)

        if not asset_absolute_path is None:
            proxy_object = HumanService.add_mhclo_asset(asset_absolute_path, basemesh, asset_type="Proxymeshes", subdiv_levels=subdiv_levels, material_type="NONE")
            if proxy_object and "name" in human_info and human_info["name"]:
                proxy_object.name = human_info["name"] + "." + proxy_object.name
            modifier = basemesh.modifiers.new("Hide base mesh", 'MASK')
            modifier.vertex_group = "body"
            modifier.invert_vertex_group = True

            uuid = GeneralObjectProperties.get_value("uuid", entity_reference=proxy_object)
            if uuid and uuid in ALL_EXTRA_GROUPS:
                for vgroup_name in ALL_EXTRA_GROUPS[uuid].keys():
                    _LOG.debug("Will create proxy vgroup", vgroup_name)
                    vgroup = proxy_object.vertex_groups.new(name=vgroup_name)
                    vgroup.add(ALL_EXTRA_GROUPS[uuid][vgroup_name], 1.0, 'ADD')
        else:
            _LOG.warn("Could not locate proxy", human_info["proxy"])
Пример #4
0
 def _populate_human_info_with_proxy_info(human_info, basemesh):
     proxy = ObjectService.find_object_of_type_amongst_nearest_relatives(basemesh, "Proxymeshes")
     if not proxy:
         return
     asset_source = GeneralObjectProperties.get_value("asset_source", entity_reference=proxy)
     if not asset_source is None:
         human_info["proxy"] = str(asset_source).strip()
Пример #5
0
 def _populate_human_info_with_bodyparts_info(human_info, basemesh):
     for bodypart in ["Eyes", "Eyelashes", "Eyebrows", "Tongue", "Teeth", "Hair"]:
         bodypart_obj = ObjectService.find_object_of_type_amongst_nearest_relatives(basemesh, bodypart)
         _LOG.debug(bodypart, bodypart_obj)
         if not bodypart_obj is None:
             asset_source = GeneralObjectProperties.get_value("asset_source", entity_reference=bodypart_obj)
             if not asset_source is None:
                 human_info[str(bodypart).lower()] = str(asset_source).strip()
Пример #6
0
    def object_is(blender_object, mpfb_type_name):
        if not blender_object:
            return False
        if not mpfb_type_name or not str(mpfb_type_name).strip():
            return False

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

        if not mpfb_type:
            return False

        return str(mpfb_type_name).lower().strip() in str(mpfb_type).lower().strip()
Пример #7
0
    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)
Пример #8
0
    def set_character_skin(mhmat_file, basemesh, bodyproxy=None, skin_type="ENHANCED_SSS", material_instances=True, slot_overrides=None):

        if bodyproxy is None:
            bodyproxy = ObjectService.find_object_of_type_amongst_nearest_relatives(basemesh, "Proxymeshes")

        material_source = os.path.basename(os.path.dirname(mhmat_file)) + "/" + os.path.basename(mhmat_file)

        _LOG.debug("material_source", material_source)

        HumanObjectProperties.set_value("material_source", material_source, entity_reference=basemesh)
        if not bodyproxy is None:
            HumanObjectProperties.set_value("material_source", material_source, entity_reference=bodyproxy)

        MaterialService.delete_all_materials(basemesh)
        if bodyproxy:
            MaterialService.delete_all_materials(bodyproxy)

        name = basemesh.name
        if not str(name).endswith(".body"):
            name = name + ".body"

        if skin_type == "MAKESKIN":
            makeskin_material = MakeSkinMaterial()
            makeskin_material.populate_from_mhmat(mhmat_file)
            blender_material = MaterialService.create_empty_material(name, basemesh)
            makeskin_material.apply_node_tree(blender_material)

        if skin_type in ["ENHANCED", "ENHANCED_SSS"]:
            presets = dict()
            presets["skin_material_type"] = skin_type

            scale_name = "METER"
            scale_factor = GeneralObjectProperties.get_value("scale_factor", entity_reference=basemesh)
            if scale_factor > 0.9:
                scale_name = "DECIMETER"
            if scale_factor > 9:
                scale_name = "CENTIMETER"

            presets["scale_factor"] = scale_name

            enhanced_material = EnhancedSkinMaterial(presets)
            enhanced_material.populate_from_mhmat(mhmat_file)
            blender_material = MaterialService.create_empty_material(name, basemesh)
            enhanced_material.apply_node_tree(blender_material)

        if material_instances:
            _LOG.debug("Will now attempt to create material slots for", (basemesh, bodyproxy))
            MaterialService.create_and_assign_material_slots(basemesh, bodyproxy)

            file_name = LocationService.get_user_config("enhanced_settings.default.json")
            settings = dict()
            _LOG.debug("Will attempt to load", file_name)
            with open(file_name, "r") as json_file:
                settings = json.load(json_file)

            _LOG.dump("Settings before overrides", settings)
            _LOG.dump("Overrides", slot_overrides)
            if not slot_overrides is None:
                for slot_name in slot_overrides.keys():
                    _LOG.debug("Reading overrides for slot", slot_name)
                    if not slot_name in settings:
                        settings[slot_name] = dict()
                    for key_name in slot_overrides[slot_name].keys():
                        _LOG.dump("Reading overrides for slot key", (slot_name, key_name, slot_overrides[slot_name][key_name]))
                        settings[slot_name][key_name] = slot_overrides[slot_name][key_name]

            _LOG.dump("Settings after overrides", settings)
            for slot in basemesh.material_slots:
                material = slot.material
                group_node = NodeService.find_first_node_by_type_name(material.node_tree, "ShaderNodeGroup")
                if group_node:
                    values = NodeService.get_socket_default_values(group_node)
                    if "colorMixIn" in values:
                        # This seems to be an enhanced skin material
                        name = material.name
                        _LOG.debug("Material name", name)
                        if "." in name:
                            name = str(name).split(".", maxsplit=1)[1]
                        if "." in name:
                            name = str(name).split(".", maxsplit=1)[0]
                        _LOG.debug("final name", name)
                        if name in settings:
                            _LOG.debug("will try to apply settings", settings[name])
                            NodeService.set_socket_default_values(group_node, settings[name])
Пример #9
0
    def add_mhclo_asset(mhclo_file, basemesh, asset_type="Clothes", subdiv_levels=1, material_type="MAKESKIN"):
        mhclo = Mhclo()
        mhclo.load(mhclo_file) # pylint: disable=E1101
        clothes = mhclo.load_mesh(bpy.context)
        clothes.location = (0.0, 0.0, 0.0)

        if not clothes or clothes is None:
            raise IOError("failed to import the clothes mesh: object was None after import")

        afn = os.path.abspath(mhclo_file)
        asset_source = os.path.basename(os.path.dirname(afn)) + "/" + os.path.basename(afn)
        GeneralObjectProperties.set_value("asset_source", asset_source, entity_reference=clothes)

        atype = str(asset_type).lower().capitalize()
        GeneralObjectProperties.set_value("object_type", atype, entity_reference=clothes)

        bpy.ops.object.shade_smooth()

        name = basemesh.name

        if "." in name:
            name = str(name).split(".")[0]

        name = name + "." + str(os.path.basename(mhclo_file)).replace(".mhclo", "").replace(".proxy", "")
        clothes.name = name

        _LOG.debug("Given name (basemesh, variable, clothes)", (basemesh.name, name, clothes.name))

        colors = MaterialService.get_diffuse_colors()
        _LOG.dump("Colors, atype, exists, mhclo.material, material_type", (colors, atype, atype in colors, mhclo.material, material_type))

        color = (0.8, 0.8, 0.8, 1.0)

        if atype in colors:
            color = colors[atype]

        if not mhclo.material:
            _LOG.debug("Material is not set in mhclo")

        if not mhclo.material is None and material_type == "MAKESKIN":
            _LOG.debug("Setting up MAKESKIN material", mhclo.material)
            MaterialService.delete_all_materials(clothes)
            makeskin_material = MakeSkinMaterial()
            makeskin_material.populate_from_mhmat(mhclo.material)
            blender_material = MaterialService.create_empty_material(name, clothes)
            makeskin_material.apply_node_tree(blender_material)
            blender_material.diffuse_color = color

        if material_type == "PROCEDURAL_EYES":
            MaterialService.delete_all_materials(clothes)
            _LOG.debug("Setting up procedural eyes")
            tree_dir = LocationService.get_mpfb_data("node_trees")
            json_file_name = os.path.join(tree_dir, "procedural_eyes.json")
            with open(json_file_name, "r") as json_file:
                node_tree_dict = json.load(json_file)
            _LOG.dump("procedural_eyes", node_tree_dict)
            blender_material = MaterialService.create_empty_material(name, clothes)
            NodeService.apply_node_tree_from_dict(blender_material.node_tree, node_tree_dict, True)
            blender_material.blend_method = "BLEND"
            blender_material.show_transparent_back = True
            blender_material.diffuse_color = color

        ClothesService.fit_clothes_to_human(clothes, basemesh, mhclo)
        mhclo.set_scalings(bpy.context, basemesh)

        delete_name = str(os.path.basename(mhclo_file)) # 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)

        rig = ObjectService.find_object_of_type_amongst_nearest_relatives(basemesh, "Skeleton")
        if rig:
            clothes.parent = rig
            modifier = clothes.modifiers.new("Armature", 'ARMATURE')
            modifier.object = rig
            ClothesService.interpolate_weights(basemesh, clothes, rig, mhclo)
        else:
            clothes.parent = basemesh

        ClothesService.set_makeclothes_object_properties_from_mhclo(clothes, mhclo, delete_group_name=delete_name)

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

        if mhclo.uuid:
            GeneralObjectProperties.set_value("uuid", mhclo.uuid, entity_reference=clothes)

        return clothes
Пример #10
0
    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)
Пример #11
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'}
Пример #12
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

        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'}
Пример #13
0
    def as_blender_mesh_object(self, parent=None, name_prefix=None):
        """Use all the collected numpy data and transform to construct a blender mesh object"""
        _LOG.enter()

        name = self._object_info.get("name", '')

        if name_prefix:
            name = name_prefix.split(
                ".")[0] + "." + name  # check if prefix has a trailing dot

        obj = ObjectService.create_blender_object_with_mesh(name)

        # Set custom properties for the generated blender object
        GeneralObjectProperties.set_value("object_type",
                                          self._object_info["type"], obj)
        GeneralObjectProperties.set_value("scale_factor", self._scale, obj)

        mesh = obj.data

        # Next most efficient available way to convert a set of numpy arrays to a mesh.
        # The most efficient way listed online causes segfaults for me and is hard to
        # understand.
        mesh.from_pydata(self._vertices.tolist(), [], self._faces.tolist())

        _LOG.dump("Vertex groups", self._vertex_groups_by_name)

        for polygon in mesh.polygons:
            # Assume all faces are smooth. At least we have no way of representing
            # sharp faces in MH
            polygon.use_smooth = True

        for name in self._vertex_groups_by_name:
            # Add all vertices to a group, with a vertex weight of 1.0.
            vgroup = obj.vertex_groups.new(name=name)
            vgroup.add(self._vertex_groups_by_name[name].tolist(), 1.0, 'ADD')

            # Update vertex weights with actual weights
            self.apply_vertex_weights_if_needed(mesh, vgroup)

        self.create_uv_layer(obj.data)

        if self._importer_presets["add_subdiv_modifier"]:
            modifier = obj.modifiers.new("Subdivision", 'SUBSURF')
            modifier.levels = 0  # viewport level
            modifier.render_levels = self._importer_presets["subdiv_levels"]

        _LOG.debug("parent", parent)
        if parent:
            _LOG.debug("parent type", parent.type)
            if parent.type == "ARMATURE":
                modifier = obj.modifiers.new("Armature", 'ARMATURE')
                modifier.object = parent
                while obj.modifiers.find(modifier.name) != 0:
                    bpy.ops.object.modifier_move_up({'object': obj},
                                                    modifier=modifier.name)

        if "Delete" in self._vertex_groups_by_name and self._vertex_groups_by_name[
                "Delete"].size > 0:
            mask = obj.modifiers.new("Hide delete group", 'MASK')
            mask.vertex_group = "Delete"
            mask.show_in_editmode = True
            mask.show_on_cage = True
            mask.invert_vertex_group = True

        ObjectService.link_blender_object(obj, collection=None, parent=parent)
        return obj