def apply_node_tree(self, blender_material, tweaks="SKIN", group_name=None):

        template_values = self.default_settings(blender_material, group_name)

        if tweaks == "SKIN":
            self.skin_tweaks(template_values, blender_material)

        # TODO: check if the group node is already there, and figure out if we should recreate
        # or reuse it. Atm, the group will always be recreated.
        # group_node = NodeService.find_node_by_name(blender_material.node_tree, template_values["group_name"])

        _LOG.dump("template_values", template_values)

        tree_dir = LocationService.get_mpfb_data("node_trees")
        json_file = os.path.join(tree_dir, "enhanced_skin.json")

        template_data = Path(json_file).read_text()
        _LOG.dump("template data before replace", template_data)

        for key in template_values:
            value = re.sub(r'\\+', '/', template_values[key])
            template_data = template_data.replace("\"$" + key + "\"", value)

        _LOG.dump("template data after replace", template_data)

        node_tree_dict = json.loads(template_data)
        _LOG.dump("node_tree_dict", node_tree_dict)

        NodeService.apply_node_tree_from_dict(blender_material.node_tree, node_tree_dict, True)
예제 #2
0
    def execute(self, context):
        _LOG.enter()
        _LOG.debug("click")

        blender_object = context.active_object
        if len(blender_object.material_slots) > 0:
            self.report({'ERROR'}, "This object already has a material")
            return {'FINISHED'}

        absolute_file_path = bpy.path.abspath(self.filepath)
        _LOG.debug("absolute_file_path", absolute_file_path)

        as_dict = dict()

        with open(absolute_file_path, "r") as json_file:
            json_data = json_file.read()

            import time
            ts = int(time.time())

            json_data = str(json_data).replace("$group_name",
                                               "node_group." + str(ts))

            as_dict = json.loads(json_data)
            self.report({'INFO'}, "JSON data read")

        _LOG.dump("loaded json data", as_dict)

        material = MaterialService.create_empty_material(
            "nodes_material", blender_object)
        NodeService.apply_node_tree_from_dict(material.node_tree, as_dict,
                                              True)

        return {'FINISHED'}
예제 #3
0
    def apply_node_tree(self, blender_material, template_values=None):
        tree_dir = LocationService.get_mpfb_data("node_trees")
        json_file = os.path.join(tree_dir, "makeskin.json")

        if template_values is None:
            template_values = dict()
            self._template(template_values, "has_bumpmap", "bumpmap_filename",
                           "bumpMapTexture")
            self._template(template_values, "has_diffuse", "diffuse_filename",
                           "diffuseTexture")
            self._template(template_values, "has_displacementmap",
                           "displacementmap_filename",
                           "displacementMapTexture")
            self._template(template_values, "has_metallicmap",
                           "metallicmap_filename", "metallicMapTexture")
            self._template(template_values, "has_normalmap",
                           "normalmap_filename", "normalMapTexture")
            self._template(template_values, "has_roughnessmap",
                           "roughnessmap_filename", "roughnessMapTexture")
            self._template(template_values, "has_transmissionmap",
                           "transmissionmap_filename",
                           "transmissionMapTexture")

        template_values["bump_or_normal"] = "false"
        if template_values["has_bumpmap"] == "true":
            template_values["bump_or_normal"] = "true"
        if template_values["has_normalmap"] == "true":
            template_values["bump_or_normal"] = "true"

        _LOG.dump("template_values", template_values)

        template_data = Path(json_file).read_text()
        for key in template_values:
            template_data = template_data.replace("\"$" + key + "\"",
                                                  template_values[key])

        _LOG.dump("Template data", template_data)

        node_tree_dict = dict()
        parse_error = None

        try:
            node_tree_dict = json.loads(template_data)
        except Exception as exc:
            _LOG.error(
                "An error was thrown when trying to parse the template data:",
                exc)
            _LOG.error("Full contents of template data",
                       "\n\n" + str(template_data) + "\n\n")
            parse_error = "Failed to parse material: " + str(
                exc) + ". See material.makeskinmaterial log for more info."

        if not parse_error is None:
            raise ValueError(parse_error)

        _LOG.dump("node_tree", node_tree_dict)

        NodeService.apply_node_tree_from_dict(blender_material.node_tree,
                                              node_tree_dict, True)
예제 #4
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
예제 #5
0
    def _assign_material(self, importer, blender_object, proxy_info=None):
        blender = importer["blender_entities"]
        ui = importer["settings_from_ui"]
        derived = importer["derived_settings"]

        name = None

        if not proxy_info:
            basic_type = "Basemesh"
            name = "body"
        else:
            basic_type = proxy_info["basic_proxy_type"]
            name = proxy_info["name"]

        if basic_type in ["Bodyproxy", "Basemesh"]:
            name = "body"

        material_name = derived["prefix"] + name
        if "materials" in blender and material_name in blender["materials"]:
            blender_object.data.materials.append(blender["materials"][material_name])
            return

        mh_material = None

        if basic_type in ["Bodyproxy", "Basemesh"]:
            if ui["skin_material_type"] == "PLAIN":
                mh_material = MakeSkinMaterial()
            else:
                mh_material = EnhancedSkinMaterial(ui)

        if basic_type in ["Bodypart", "Eyes", "Clothes"]:
            if "Eye" in basic_type and ui["procedural_eyes"]:
                mh_material = "procedural_eyes"
            else:
                mh_material = MakeSkinMaterial()

        if mh_material:
            blender_material = MaterialService.create_empty_material(material_name, blender_object)
            if not "materials" in blender:
                blender["materials"] = dict()
            blender["materials"][material_name] = blender_material

            if basic_type == "Basemesh":
                mh_material.populate_from_body_material_socket_call()
            else:
                if mh_material != "procedural_eyes":
                    mh_material.populate_from_proxy_material_socket_call(proxy_info["uuid"])

            if isinstance(mh_material, EnhancedSkinMaterial):
                name = derived["prefix"] + derived["name"]
                mh_material.apply_node_tree(blender_material, group_name=material_name)
            else:
                if mh_material != "procedural_eyes":
                    mh_material.apply_node_tree(blender_material)
                else:
                    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)
                    NodeService.apply_node_tree_from_dict(blender_material.node_tree, node_tree_dict, True)

            diffuse_colors = MaterialService.get_diffuse_colors()
            if basic_type in diffuse_colors:
                blender_material.diffuse_color = diffuse_colors[basic_type]
            if proxy_info and proxy_info["type"] in diffuse_colors:
                blender_material.diffuse_color = diffuse_colors[proxy_info["type"]]