예제 #1
0
    def draw(self, context):
        _LOG.enter()

        # TODO: this section should probably also be present in the importer panel
        default_json = LocationService.get_user_config(
            "enhanced_settings.default.json")
        if not os.path.exists(default_json):
            _LOG.warn(
                "The default enhanced settings do not exist. Will create at",
                default_json)
            template_settings = LocationService.get_mpfb_data("settings")
            default_json_template = os.path.join(
                template_settings, "enhanced_settings.default.json")
            _LOG.warn("Copying from", default_json_template)
            shutil.copy(default_json_template, default_json)
        else:
            _LOG.trace("Default enhanced settings exist")

        if UiService.get_enhanced_settings_panel_list() is None:
            UiService.rebuild_enhanced_settings_panel_list()

        layout = self.layout
        scene = context.scene

        self._load_save_box(
            scene, self._create_box(layout, "Load/save presets", "MODIFIER"))
예제 #2
0
    def draw(self, context):
        _LOG.enter()
        layout = self.layout

        user_files = LocationService.get_user_home()
        library_files = LocationService.get_user_data()
        system_data = LocationService.get_mpfb_data()
        log_files = LocationService.get_user_home("logs")

        self._path(layout, "User files", user_files)
        self._path(layout, "Library files", library_files)
        self._path(layout, "System data", system_data)
        self._path(layout, "Log files", log_files)
예제 #3
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'}
    def draw(self, context):
        _LOG.enter()

        default_json = LocationService.get_user_config(
            "importer_presets.default.json")
        if not os.path.exists(default_json):
            _LOG.warn(
                "The default importer presets do not exist. Will create these."
            )
            excludes = ["available_presets", "name"]
            IMPORTER_PRESETS_PROPERTIES.serialize_to_json(
                default_json, entity_reference=context, exclude_keys=excludes)
        else:
            _LOG.trace("Default presets exist")

        if UiService.get_importer_presets_panel_list() is None:
            UiService.rebuild_importer_presets_panel_list()

        layout = self.layout
        scene = context.scene

        self._load_save_box(
            scene, self._create_box(layout, "Load/save presets", "MODIFIER"))
        self._what_box(scene,
                       self._create_box(layout, "What to import", "MODIFIER"))
        self._general_box(scene, self._create_box(layout, "General",
                                                  "MODIFIER"))
        self._mesh_and_groups_box(
            scene, self._create_box(layout, "Mesh and vGroups", "MODIFIER"))
        self._materials_box(scene,
                            self._create_box(layout, "Materials", "MODIFIER"))
        self._network_box(scene, self._create_box(layout, "Network",
                                                  "MODIFIER"))
예제 #5
0
    def execute(self, context):
        _LOG.enter()
        name = IMPORTER_PRESETS_PROPERTIES.get_value("name", entity_reference=context.scene)
        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'}, "Presets names should not contain spaces")
            return {'FINISHED'}

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

        excludes = ["available_presets", "name"]
        IMPORTER_PRESETS_PROPERTIES.serialize_to_json(file_name, entity_reference=context.scene, exclude_keys=excludes)

        UiService.rebuild_importer_presets_panel_list()
        UiService.rebuild_importer_panel_list()
        self.report({'INFO'}, "Presets were written to " + file_name)
        return {'FINISHED'}
    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)
예제 #7
0
def ensure_eye_settings_default_exists():
    """Check that the json file with the default eye settings exists in the user config dir.
    If not, copy it from the data directory."""
    _LOG.enter()
    default_json = LocationService.get_user_config("eye_settings.default.json")
    if not os.path.exists(default_json):
        _LOG.warn("The default eye settings do not exist. Will create at",
                  default_json)
        template_settings = LocationService.get_mpfb_data("settings")
        default_json_template = os.path.join(template_settings,
                                             "eye_settings.default.json")
        if os.path.exists(default_json_template):
            _LOG.warn("Copying from", default_json_template)
            shutil.copy(default_json_template, default_json)
    else:
        _LOG.trace("Default eye settings exist")
예제 #8
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)
예제 #9
0
 def _get_config_file(self):
     global _CONFIG_FILE
     if _CONFIG_FILE is None:
         metadata = LocationService.get_mpfb_data("mesh_metadata")
         config_file = os.path.join(metadata, "hm08_config.json")
         with open(config_file, 'r') as json_file:
             _CONFIG_FILE = json.load(json_file)
     return _CONFIG_FILE
예제 #10
0
    def get_available_data_roots():
        _LOG.enter()
        user_data = LocationService.get_user_data()
        mh_data = LocationService.get_mh_user_data()
        mpfb_data = LocationService.get_mpfb_data()

        _LOG.dump("Data roots raw", [mpfb_data, mh_data, user_data])

        roots = []
        for root in [mpfb_data, mh_data, user_data]:
            if not root is None:
                if os.path.exists(root):
                    roots.append(root)

        _LOG.dump("Data roots checked", roots)

        return roots
예제 #11
0
 def update_list_of_human_presets():
     global _EXISTING_PRESETS
     confdir = LocationService.get_user_config()
     _EXISTING_PRESETS = []
     for filename in os.listdir(confdir):
         if fnmatch.fnmatch(filename, "human.*.json"):
             match = re.search(r'^human.(.*).json$', filename)
             if match and match.group(1):
                 _EXISTING_PRESETS.append(match.group(1))
     _EXISTING_PRESETS.sort()
예제 #12
0
 def execute(self, context):
     _LOG.enter()
     name = IMPORTER_PRESETS_PROPERTIES.get_value(
         "available_presets", entity_reference=context.scene)
     file_name = LocationService.get_user_config("importer_presets." +
                                                 name + ".json")
     IMPORTER_PRESETS_PROPERTIES.deserialize_from_json(
         file_name, entity_reference=context.scene)
     self.report({'INFO'}, "Presets were loaded from " + file_name)
     return {'FINISHED'}
예제 #13
0
 def execute(self, context):
     _LOG.enter()
     name = IMPORTER_PRESETS_PROPERTIES.get_value(
         "available_presets", entity_reference=context.scene)
     file_name = LocationService.get_user_config("importer_presets." +
                                                 name + ".json")
     excludes = ["available_presets", "name"]
     IMPORTER_PRESETS_PROPERTIES.serialize_to_json(
         file_name, entity_reference=context.scene, exclude_keys=excludes)
     self.report({'INFO'}, "Presets were written to " + file_name)
     return {'FINISHED'}
예제 #14
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
예제 #15
0
    def execute(self, context):

        _LOG.reset_timer()
        from mpfb.ui.newhuman.frompresetspanel import PRESETS_HUMAN_PROPERTIES  # pylint: disable=C0415

        name = PRESETS_HUMAN_PROPERTIES.get_value("available_presets", entity_reference=context.scene)

        if name is None or str(name).strip() == "":
            self.report({'ERROR'}, "Presets must be selected")
            return {'FINISHED'}

        detailed_helpers = PRESETS_HUMAN_PROPERTIES.get_value("detailed_helpers", entity_reference=context.scene)
        extra_vertex_groups = PRESETS_HUMAN_PROPERTIES.get_value("extra_vertex_groups", entity_reference=context.scene)
        mask_helpers = PRESETS_HUMAN_PROPERTIES.get_value("mask_helpers", entity_reference=context.scene)
        scale_factor = PRESETS_HUMAN_PROPERTIES.get_value("scale_factor", entity_reference=context.scene)

        scale = 0.1

        if scale_factor == "DECIMETER":
            scale = 1.0

        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'}
예제 #16
0
 def get_base_mesh_vertex_group_definition():
     global _BASEMESH_VERTEX_GROUPS_EXPANDED # pylint: disable=W0603
     global _BASEMESH_VERTEX_GROUPS_UNEXPANDED # pylint: disable=W0603
     if _BASEMESH_VERTEX_GROUPS_EXPANDED is None:
         meta_data_dir = LocationService.get_mpfb_data("mesh_metadata")
         definition_file = os.path.join(meta_data_dir, "basemesh_vertex_groups.json")
         with open(definition_file, "r") as json_file:
             _BASEMESH_VERTEX_GROUPS_UNEXPANDED = json.load(json_file)
         _BASEMESH_VERTEX_GROUPS_EXPANDED = dict()
         for group in _BASEMESH_VERTEX_GROUPS_UNEXPANDED.keys():
             group_name = str(group)
             _BASEMESH_VERTEX_GROUPS_EXPANDED[group_name] = []
             for start_stop in _BASEMESH_VERTEX_GROUPS_UNEXPANDED[group]:
                 _BASEMESH_VERTEX_GROUPS_EXPANDED[group_name].extend(range(start_stop[0], start_stop[1]))
         _BASEMESH_VERTEX_GROUPS_EXPANDED.update(BASEMESH_EXTRA_GROUPS)
     # Return a copy so it doesn't get accidentally modified
     return dict(_BASEMESH_VERTEX_GROUPS_EXPANDED)
예제 #17
0
    def execute(self, context):
        _LOG.enter()

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

        name = EYE_SETTINGS_PROPERTIES.get_value("available_settings", entity_reference=context)
        if not name is None:
            name = str(name).strip()
        if name == "" or name is None:
            self.report({'ERROR'}, "Settings must be chosen from the list")
            return {'FINISHED'}

        confdir = LocationService.get_user_config()
        file_name = os.path.join(confdir, "eye_settings." + name + ".json")

        return _save_material(self, context, file_name)
예제 #18
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("available_presets", entity_reference=context)
        if not name is None:
            name = str(name).strip()
        if name == "" or name is None:
            self.report({'ERROR'}, "Presets must be chosen from the list")
            return {'FINISHED'}

        confdir = LocationService.get_user_config()
        file_name = os.path.join(confdir, "human." + name + ".json")

        return {'FINISHED'}
예제 #19
0
    def add_standard_rig(basemesh, rig_name, import_weights=True):
        rigs_dir = LocationService.get_mpfb_data("rigs")
        standard_dir = os.path.join(rigs_dir, "standard")
        rig_file = os.path.join(standard_dir, "rig." + rig_name + ".json")
        rig = Rig.from_json_file_and_basemesh(rig_file, basemesh)
        armature_object = rig.create_armature_and_fit_to_basemesh()
        basemesh.parent = armature_object

        armature_object.location = basemesh.location
        basemesh.location = (0.0, 0.0, 0.0)

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

        return armature_object
예제 #20
0
    def _get_settings_from_ui(self, context):
        _LOG.enter()

        selected_presets = IMPORTER_PROPERTIES.get_value("presets_for_import", entity_reference=context, default_value="FROM_UI")
        _LOG.debug("import with presets:", selected_presets)

        json_with_overrides = None
        if selected_presets != "FROM_UI":
            json_with_overrides = LocationService.get_user_config("importer_presets." + selected_presets + ".json")
            _LOG.debug("Using overrides from", json_with_overrides)

        settings = IMPORTER_PRESETS_PROPERTIES.as_dict(entity_reference=context, json_with_overrides=json_with_overrides)

        settings["skin_settings_for_import"] = IMPORTER_PROPERTIES.get_value("skin_settings_for_import", entity_reference=context, default_value="default")
        settings["eye_settings_for_import"] = IMPORTER_PROPERTIES.get_value("eye_settings_for_import", entity_reference=context, default_value="default")

        _LOG.dump("Settings to use", settings)

        return settings
예제 #21
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'}
예제 #22
0
    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'}
    def default_settings(self, blender_material, group_name=None):
        tex_dir = LocationService.get_mpfb_data("textures")
        sss_file = os.path.join(tex_dir, "sss.png")

        template_values = dict()
        self._template(template_values, "has_diffusetexture", "diffusetexture_filename", "diffuseTexture")
        self._template(template_values, "has_normalmap", "normalmap_filename", "normalMapTexture")

        mat_type = str(self.presets["skin_material_type"]).lower()

        if "sss" in mat_type:
            template_values["has_sss"] = "true"
        else:
            template_values["has_sss"] = "false"

        template_values["ssstexture_filename"] = "\"" + sss_file + "\""
        template_values["sss_radius_scale"] = "0.1"

        if "scale_factor" in self.presets:
            factor = self.presets["scale_factor"]
            if factor == "DECIMETER":
                template_values["sss_radius_scale"] = "1"
            if factor == "CENTIMETER":
                template_values["sss_radius_scale"] = "10"

        template_values["Roughness"] = "0.5"

        if group_name:
            template_values["group_name"] = "\"" + group_name + "\""
        else:
            if blender_material.name:
                template_values["group_name"] = "\"" + blender_material.name + "\""
            else:
                template_values["group_name"] = "\"mpfb_enhanced_skin\""

        return template_values
예제 #24
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'}
예제 #25
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])
예제 #26
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
예제 #27
0
    def execute(self, context):
        _LOG.enter()

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

        name = ENHANCED_SETTINGS_PROPERTIES.get_value("available_settings",
                                                      entity_reference=context)

        if not name:
            self.report({'ERROR'}, "Must select settings to load")
            return {'FINISHED'}

        file_name = LocationService.get_user_config("enhanced_settings." +
                                                    name + ".json")

        if not os.path.exists(file_name):
            _LOG.error("Settings did not exist despite being in list:",
                       file_name)
            self.report({'ERROR'}, "Settings did not exist!?")
            return {'FINISHED'}

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

        body = ObjectService.find_object_of_type_amongst_nearest_relatives(
            context.object, "Basemesh")
        if not body:
            body = ObjectService.find_object_of_type_amongst_nearest_relatives(
                context.object, "Proxymesh")

        if not body:
            self.report({
                'ERROR'
            }, "Could not find basemesh or body proxy amongst nearest relatives"
                        )
            return {'FINISHED'}

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

        _LOG.debug("material_slots", body.material_slots)

        for slot in body.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
                    if "." in name:
                        (prefix, name) = str(name).split(".", maxsplit=1)
                    if "." in name:
                        (name, number) = str(name).split(".", maxsplit=1)
                    _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])

        self.report({'INFO'}, "Presets were loaded from " + file_name)
        return {'FINISHED'}
예제 #28
0
"""Icons for the modeling panels"""

from mpfb.services.locationservice import LocationService
from mpfb.services.logservice import LogService
import bpy.utils.previews
import os, re

_LOG = LogService.get_logger("model.modelingicons")

MODELING_ICONS = bpy.utils.previews.new()

_TARGETS_DIR = LocationService.get_mpfb_data("targets")
_IMAGES_DIR = os.path.join(_TARGETS_DIR, "_images")

for image in os.listdir(_IMAGES_DIR):
    if ".png" in image:
        name = re.sub(r"\.png$", "", image)
        name = re.sub("^r-", "", name)
        name = re.sub("^l-", "", name)
        image_path = os.path.join(_IMAGES_DIR, image)
        _LOG.debug("Will try to load icon", (name, image_path))
        MODELING_ICONS.load(name, image_path, 'IMAGE')
예제 #29
0
"""Macro subpanel for modeling humans"""

import bpy, os, json
from bpy.props import FloatProperty
from mpfb import ClassManager
from mpfb.services.logservice import LogService
from mpfb.services.locationservice import LocationService
from mpfb.services.objectservice import ObjectService
from mpfb.services.targetservice import TargetService
from mpfb.entities.objectproperties import HumanObjectProperties

_LOG = LogService.get_logger("model.macrosubpanel")

_TARGETS_DIR = LocationService.get_mpfb_data("targets")
_LOG.debug("Target dir:", _TARGETS_DIR)

_INTERNAL_PREFIX = "mpfb_macropanel_"

_MACROTARGETS = {
        "Macrodetails": [
            "gender",
            "age",
            "muscle",
            "weight",
            "height",
            "proportions"
            ],
        "Breast shape": [
            "cupsize",
            "firmness"
            ],
예제 #30
0
    def execute(self, context):
        _LOG.enter()

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

        name = EYE_SETTINGS_PROPERTIES.get_value("available_settings",
                                                 entity_reference=context)

        if not name:
            self.report({'ERROR'}, "Must select settings to load")
            return {'FINISHED'}

        file_name = LocationService.get_user_config("eye_settings." + name +
                                                    ".json")

        if not os.path.exists(file_name):
            _LOG.error("Settings did not exist despite being in list:",
                       file_name)
            self.report({'ERROR'}, "Settings did not exist!?")
            return {'FINISHED'}

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

        eyes = ObjectService.find_object_of_type_amongst_nearest_relatives(
            context.object, "Eyes")

        if not eyes:
            self.report({'ERROR'},
                        "Could not find eyes amongst nearest relatives")
            return {'FINISHED'}

        if not MaterialService.has_materials(eyes):
            self.report({'ERROR'}, "Eyes do not have a material")
            return {'FINISHED'}

        _LOG.debug("material_slots", eyes.material_slots)

        slot = eyes.material_slots[0]

        material = slot.material
        group_node = NodeService.find_first_node_by_type_name(
            material.node_tree, "ShaderNodeGroup")
        if group_node:
            material_settings = NodeService.get_socket_default_values(
                group_node)
            if "IrisMinorColor" in material_settings:
                _LOG.debug("will try to apply settings", settings)
                NodeService.set_socket_default_values(group_node, settings)
            else:
                self.report(
                    {'ERROR'},
                    "Eyes do not seem to have procedural eyes material")
                return {'FINISHED'}
        else:
            self.report({'ERROR'},
                        "Eyes do not seem to have procedural eyes material")
            return {'FINISHED'}

        self.report({'INFO'}, "Settings were loaded from " + file_name)
        return {'FINISHED'}