from mpfb import ClassManager _LOG = LogService.get_logger("makeclothes.markclothes") class MPFB_OT_MarkClothesOperator(bpy.types.Operator): """Set mesh type to clothes""" bl_idname = "mpfb.mark_makeclothes_clothes" bl_label = "Mark as clothes" bl_options = {'REGISTER'} @classmethod def poll(cls, context): if context.active_object is not None: return context.active_object.type == "MESH" return False def execute(self, context): blender_object = context.active_object scene = context.scene from mpfb.ui.makeclothes.makeclothespanel import MAKECLOTHES_PROPERTIES # pylint: disable=C0415 from mpfb.ui.makeclothes import MakeClothesObjectProperties # pylint: disable=C0415 self.report({'INFO'}, "Mesh type was set to clothes") return {'FINISHED'} ClassManager.add_class(MPFB_OT_MarkClothesOperator)
"""Operator for opening web browser""" import webbrowser, bpy from bpy.props import StringProperty from mpfb.services.logservice import LogService from mpfb import ClassManager _LOG = LogService.get_logger("webresources.webresource") class MPFB_OT_Web_Resource_Operator(bpy.types.Operator): """Open web browser""" bl_idname = "mpfb.web_resource" bl_label = "Open" bl_options = {'REGISTER'} url: StringProperty(name="url", description="Address to open", default="") def execute(self, context): webbrowser.open(self.url) return {'FINISHED'} ClassManager.add_class(MPFB_OT_Web_Resource_Operator)
def invoke(self, context, event): blender_object = context.active_object name = MakeTargetObjectProperties.get_value( "name", entity_reference=blender_object) self.filepath = bpy.path.clean_name(name, replace="-") + ".target" return super().invoke(context, event) def execute(self, context): blender_object = context.active_object target_string = Path(self.filepath).read_text() TargetService.target_string_to_shape_key(target_string, "PrimaryTarget", blender_object) # This might look strange, but it is to ensure the name attribute of the object # is not still null if left at its default name = MakeTargetObjectProperties.get_value( "name", entity_reference=blender_object) MakeTargetObjectProperties.set_value("name", name, entity_reference=blender_object) self.report({'INFO'}, "Target was imported as shape key") return {'FINISHED'} ClassManager.add_class(MPFB_OT_ImportTargetOperator)
blender_object = context.active_object file_name = bpy.path.abspath(self.filepath) if not MaterialService.has_materials(blender_object): self.report({'ERROR'}, "Object does not have a material") return {'FINISHED'} material = MakeSkinMaterial() material.populate_from_object(blender_object) mhmat_string = material.as_mhmat() _LOG.dump("material", mhmat_string) image_file_error = material.check_that_all_textures_are_saved( blender_object) if not image_file_error is None: self.report({'ERROR'}, image_file_error) return {'FINISHED'} # TODO: copy normalized images with open(file_name, "w") as mhmat: mhmat.write(mhmat_string) self.report({'INFO'}, "The MHMAT file was written as " + file_name) return {'FINISHED'} ClassManager.add_class(MPFB_OT_WriteMaterialOperator)
def execute(self, context): obj = context.active_object scn = context.scene from mpfb.ui.makeskin.makeskinpanel import MAKESKIN_PROPERTIES if MaterialService.has_materials(obj): if not MAKESKIN_PROPERTIES.get_value("overwrite", entity_reference=scn): self.report({ 'ERROR' }, "A material for this object already exists, change 'replace' option in common settings to overwrite material" ) return {'FINISHED'} else: while len(obj.data.materials) > 0: obj.data.materials.pop(index=0) material = MaterialService.create_empty_material( "makeskinmaterial", obj) mhmat = MakeSkinMaterial() mhmat.populate_from_mhmat(self.filepath) mhmat.apply_node_tree(material) self.report({'INFO'}, "Material imported") return {'FINISHED'} ClassManager.add_class(MPFB_OT_ImportMaterialOperator)
description="Set target value", max=1.0, min=_min_val) setattr(bpy.types.Scene, _right_name, prop) _LOG.debug("property", prop) else: prop = FloatProperty(name=_unsided_name, get=_get_wrapper_unsided, set=_set_wrapper_unsided, description="Set target value", max=1.0, min=_min_val) setattr(bpy.types.Scene, _unsided_name, prop) _LOG.debug("property", prop) _i = _i + 1 definition = { "bl_label": _section["label"], "target_dir": os.path.join(_TARGETS_DIR, name), "section": _section, "section_name": name } sub_panel = type("MPFB_PT_Model_Sub_Panel_" + name, (_Abstract_Model_Panel, ), definition) _LOG.debug("sub_panel", sub_panel) ClassManager.add_class(sub_panel)
layout = self.layout scene = context.scene if not context.object: return if not ObjectService.object_is_basemesh(context.object): return basemesh = context.object for category_name in _MACROTARGETS.keys(): targets = _MACROTARGETS[category_name] self._draw_category(scene, layout, category_name, targets, basemesh) ClassManager.add_class(MPFB_PT_Macro_Sub_Panel) _PROPS_DIR = os.path.join(LocationService.get_mpfb_root("entities"), "objectproperties", "humanproperties") def _general_set_target_value(name, value): _LOG.trace("_general_set_target_value", (name, value)) basemesh = bpy.context.object HumanObjectProperties.set_value(name, value, entity_reference=basemesh) TargetService.reapply_macro_details(basemesh) #=========================================================================== # macro_info = TargetService.get_macro_info_dict_from_basemesh(basemesh) # _LOG.debug("macro_info", macro_info) # target_stack = TargetService.calculate_target_stack_from_macro_info_dict(macro_info) # _LOG.debug("target_stack", target_stack) #===========================================================================
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'} ClassManager.add_class(MPFB_OT_HumanFromPresetsOperator)
class MPFB_OT_CreateTargetOperator(bpy.types.Operator): """Create primary target""" bl_idname = "mpfb.create_maketarget_target" bl_label = "Create target" bl_options = {'REGISTER', 'UNDO'} @classmethod def poll(cls, context): if not ObjectService.object_is_basemesh(context.active_object): return False return not context.active_object.data.shape_keys def execute(self, context): blender_object = context.active_object TargetService.create_shape_key(blender_object, "PrimaryTarget") # This might look strange, but it is to ensure the name attribute of the object # is not still null if left at its default name = MakeTargetObjectProperties.get_value( "name", entity_reference=blender_object) MakeTargetObjectProperties.set_value("name", name, entity_reference=blender_object) self.report({'INFO'}, "Primary target created") return {'FINISHED'} ClassManager.add_class(MPFB_OT_CreateTargetOperator)
basemesh = HumanService.create_human( mask_helpers=mask_helpers, detailed_helpers=detailed_helpers, extra_vertex_groups=extra_vertex_groups, feet_on_ground=True, scale=scale, macro_detail_dict=macro_details) self.report({ 'INFO' }, "Human created. You can adjust the phenotype values on the modeling panel." ) else: basemesh = HumanService.create_human( mask_helpers=mask_helpers, detailed_helpers=detailed_helpers, extra_vertex_groups=extra_vertex_groups, feet_on_ground=True, scale=scale) self.report({'INFO'}, "Human created.") _LOG.debug("Basemesh", basemesh) bpy.ops.object.select_all(action='DESELECT') bpy.context.view_layer.objects.active = basemesh basemesh.select_set(True) return {'FINISHED'} ClassManager.add_class(MPFB_OT_CreateHumanOperator)
from mpfb import ClassManager _LOG = LogService.get_logger("makeclothes.extractclothes") class MPFB_OT_ExtractClothesOperator(bpy.types.Operator): """Extract clothes from base mesh helpers""" bl_idname = "mpfb.extract_makeclothes_clothes" bl_label = "Extract clothes" bl_options = {'REGISTER'} @classmethod def poll(cls, context): if context.active_object is not None: return context.active_object.type == "MESH" return False def execute(self, context): blender_object = context.active_object scene = context.scene from mpfb.ui.makeclothes.makeclothespanel import MAKECLOTHES_PROPERTIES # pylint: disable=C0415 from mpfb.ui.makeclothes import MakeClothesObjectProperties # pylint: disable=C0415 self.report({'INFO'}, "Clothes mesh was created") return {'FINISHED'} ClassManager.add_class(MPFB_OT_ExtractClothesOperator)
@classmethod def poll(cls, context): return context.active_object is not None def invoke(self, context, event): # TODO: support blender materials #======================================================================= # if not self.filepath: # blend_filepath = context.active_object.MhMsName # # just in case ... ;) # if not blend_filepath: # blend_filepath = "untitled" # self.filepath = blend_filepath + self.filename_ext #======================================================================= context.window_manager.fileselect_add(self) return {'RUNNING_MODAL'} def execute(self, context): blender_object = context.active_object file_name = bpy.path.abspath(self.filepath) self.report({'INFO'}, "The MHCLO file was written as " + file_name) return {'FINISHED'} ClassManager.add_class(MPFB_OT_WriteClothesOperator)
def execute(self, context): _LOG.debug("filepath", self.filepath) from mpfb.ui.assetlibrary.assetsettingspanel import ASSET_SETTINGS_PROPERTIES # pylint: disable=C0415 scene = context.scene skin_type = ASSET_SETTINGS_PROPERTIES.get_value("skin_type", entity_reference=scene) material_instances = ASSET_SETTINGS_PROPERTIES.get_value( "material_instances", entity_reference=scene) blender_object = context.active_object basemesh = ObjectService.find_object_of_type_amongst_nearest_relatives( blender_object, "Basemesh") bodyproxy = ObjectService.find_object_of_type_amongst_nearest_relatives( blender_object, "Proxymeshes") HumanService.set_character_skin(self.filepath, basemesh, bodyproxy=bodyproxy, skin_type=skin_type, material_instances=material_instances) self.report({'INFO'}, "Skin was loaded") return {'FINISHED'} ClassManager.add_class(MPFB_OT_Load_Library_Skin_Operator)
class MPFB_OT_PrintTargetOperator(bpy.types.Operator): """Dump target data to console""" bl_idname = "mpfb.print_maketarget_target" bl_label = "Print target" bl_options = {'REGISTER'} @classmethod def poll(cls, context): if not ObjectService.object_is_basemesh(context.active_object): return False if context.active_object.data.shape_keys: return True return False def execute(self, context): blender_object = context.active_object info = TargetService.get_shape_key_as_dict(blender_object, "PrimaryTarget") _LOG.dump("Shape key", info) print(TargetService.shape_key_info_as_target_string(info)) self.report({'INFO'}, "Target printed to console") return {'FINISHED'} ClassManager.add_class(MPFB_OT_PrintTargetOperator)
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'} ClassManager.add_class(MPFB_OT_AddStandardRigOperator)
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'} ClassManager.add_class(MPFB_OT_Load_Library_Proxy_Operator)
return box def _refit(self, scene, layout): box = self._create_box(layout, "Refit") #======================================================================= # NEW_HUMAN_PROPERTIES.draw_properties(scene, box, [ # "scale_factor", # "detailed_helpers", # "extra_vertex_groups", # "mask_helpers" # ]) # box.operator('mpfb.create_human') #======================================================================= def draw(self, context): _LOG.enter() layout = self.layout scene = context.scene self._refit(scene, layout) @classmethod def poll(cls, context): return ObjectService.object_is_basemesh(context.active_object) ClassManager.add_class(MPFB_PT_Model_Panel) from ._macrosubpanel import MPFB_PT_Macro_Sub_Panel from ._modelsubpanels import *
bl_label = "Load pack from zip file" bl_options = {'REGISTER'} filter_glob: StringProperty(default='*.zip', options={'HIDDEN'}) 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'} ClassManager.add_class(MPFB_OT_Load_Pack_Operator)
"mask_helpers" ]) box.operator('mpfb.create_human') def _phenotype(self, scene, layout): box = self._create_box(layout, "Phenotype") NEW_HUMAN_PROPERTIES.draw_properties(scene, box, [ "phenotype_gender", "phenotype_age", "phenotype_muscle", "phenotype_weight", "phenotype_height", "phenotype_race", "add_phenotype", "phenotype_influence" ]) def _breast(self, scene, layout): box = self._create_box(layout, "Breast") NEW_HUMAN_PROPERTIES.draw_properties(scene, box, [ "phenotype_breastsize", "phenotype_breastfirmness", "add_breast", "breast_influence" ]) def draw(self, context): _LOG.enter() layout = self.layout scene = context.scene self._phenotype(scene, layout) self._breast(scene, layout) self._create(scene, layout) ClassManager.add_class(MPFB_PT_NewHuman_Panel)
if interpolate_weights and basemesh is None: self.report({ 'ERROR' }, "interpolate weights is enabled, but active object is not a base mesh" ) return {'FINISHED'} if set_up_rigging and rig is None: self.report({ 'ERROR' }, "set up rigging is enabled, but could not find a rig to attach to" ) return {'FINISHED'} if not add_subdiv_modifier: subdiv_levels = 0 _LOG.debug("Will call add_mhclo_asset: (asset_type, material_type)", (self.object_type, self.material_type)) HumanService.add_mhclo_asset(self.filepath, basemesh, asset_type=self.object_type, subdiv_levels=subdiv_levels, material_type=self.material_type) self.report({'INFO'}, "Clothes were loaded") return {'FINISHED'} ClassManager.add_class(MPFB_OT_Load_Library_Clothes_Operator)
class MPFB_PT_Add_Rig_Panel(Abstract_Panel): """Functionality for adding/setting rig""" bl_label = "Add rig" bl_category = UiService.get_value("MODELCATEGORY") bl_parent_id = "MPFB_PT_Rig_Panel" def _standard_rig(self, scene, layout): box = self.create_box(layout, "Add standard rig") props = ["standard_rig", "import_weights"] ADD_RIG_PROPERTIES.draw_properties(scene, box, props) box.operator('mpfb.add_standard_rig') def _rigify_rig(self, scene, layout): box = self.create_box(layout, "Add rigify rig") props = ["import_weights_rigify", "delete_after_generate", "generate"] ADD_RIG_PROPERTIES.draw_properties(scene, box, props) box.operator('mpfb.add_rigify_rig') box.operator('mpfb.generate_rigify_rig') def draw(self, context): _LOG.enter() layout = self.layout scene = context.scene self._standard_rig(scene, layout) self._rigify_rig(scene, layout) ClassManager.add_class(MPFB_PT_Add_Rig_Panel)
from mpfb.services.objectservice import ObjectService from mpfb.services.targetservice import TargetService from mpfb import ClassManager _LOG = LogService.get_logger("maketarget.symmetrizeleft") class MPFB_OT_SymmetrizeLeftOperator(bpy.types.Operator): """Symmetrize by taking the right side of the model and copy it mirrored to the left side""" bl_idname = "mpfb.symmetrize_maketarget_left" bl_label = "Copy -x to +x" bl_options = {'REGISTER', 'UNDO'} @classmethod def poll(cls, context): if not ObjectService.object_is_basemesh(context.active_object): return False if context.active_object.data.shape_keys: return True return False def execute(self, context): blender_object = context.active_object TargetService.symmetrize_shape_key(blender_object, "PrimaryTarget", False) self.report({'INFO'}, "Target symmetrized") return {'FINISHED'} ClassManager.add_class(MPFB_OT_SymmetrizeLeftOperator)
box.operator('mpfb.import_makeskin_material') def _save_material(self, blender_object, layout): box = self._create_box(layout, "Write material", "MATERIAL_DATA") props = [ "name", "description", "tag", "license", "author", "homepage", "backface_culling", "cast_shadows", "receive_shadows", "alpha_to_coverage", "shadeless", "wireframe", "transparent", "depthless", "sss_enable", "auto_blend", "textures", "use_litsphere", "litsphere" ] MakeSkinObjectProperties.draw_properties(blender_object, box, props) box.operator('mpfb.write_makeskin_material') def draw(self, context): _LOG.enter() layout = self.layout scene = context.scene blender_object = context.active_object if blender_object is None: return if blender_object.type == "MESH": self._create_material(scene, layout) self._import_material(layout) self._save_material(blender_object, layout) ClassManager.add_class(MPFB_PT_MakeSkin_Panel)
box.operator('mpfb.symmetrize_maketarget_left') box.operator('mpfb.symmetrize_maketarget_right') def _debug_target(self, scene, layout): box = self._create_box(layout, "Debug", "TOOL_SETTINGS") box.operator('mpfb.print_maketarget_target') 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) ClassManager.add_class(MPFB_PT_MakeTarget_Panel)
box.operator('mpfb.mark_makeclothes_clothes') def _write_clothes(self, blender_object, scene, layout): box = self._create_box(layout, "Write clothes", "MATERIAL_DATA") props = ["overwrite"] MAKECLOTHES_PROPERTIES.draw_properties(scene, box, props) props = ["name", "description", "tag", "license", "author", "homepage"] MakeClothesObjectProperties.draw_properties(blender_object, box, props) box.operator('mpfb.write_makeclothes_clothes') def draw(self, context): _LOG.enter() layout = self.layout scene = context.scene blender_object = context.active_object #self._setup_clothes(scene, layout) if blender_object is None: return #if blender_object.type == "MESH": # self._write_clothes(blender_object, scene, layout) ClassManager.add_class(MPFB_PT_MakeClothes_Panel)
for child in ObjectService.get_list_of_children(armature_object): child.parent = rigify_object for bone in armature_object.data.bones: name = bone.name if name in child.vertex_groups and not "teeth" in name: vertex_group = child.vertex_groups.get(name) vertex_group.name = "DEF-" + name for modifier in child.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 generated") return {'FINISHED'} ClassManager.add_class(MPFB_OT_GenerateRigifyRigOperator)
_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'} ClassManager.add_class(MPFB_OT_AddRigifyRigOperator)
class MPFB_PT_From_Presets_Panel(Abstract_Panel): """Create human from preset main panel.""" bl_label = "From presets" bl_space_type = "VIEW_3D" bl_region_type = "UI" bl_category = UiService.get_value("MODELCATEGORY") bl_options = {'DEFAULT_CLOSED'} bl_parent_id = "MPFB_PT_New_Panel" def _create(self, scene, layout): PRESETS_HUMAN_PROPERTIES.draw_properties(scene, layout, [ "available_presets", "scale_factor", "detailed_helpers", "extra_vertex_groups", "mask_helpers" ]) layout.operator('mpfb.human_from_presets') def draw(self, context): _LOG.enter() layout = self.layout scene = context.scene self._create(scene, layout) ClassManager.add_class(MPFB_PT_From_Presets_Panel)