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"))
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)
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"))
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)
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")
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)
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
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
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()
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'}
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'}
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
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'}
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)
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)
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'}
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
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
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'}
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
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'}
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])
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
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'}
"""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')
"""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" ],
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'}