From 8dcce4c1d49691bb5c18b90b96f4f7bf0e92a44c Mon Sep 17 00:00:00 2001 From: UuuNyaa Date: Thu, 7 Apr 2022 00:53:19 -0700 Subject: [PATCH] Add attach meshes API --- mmd_tools/__init__.py | 2 +- mmd_tools/core/model.py | 49 +++++++++++++++++++++++++++++----- mmd_tools/core/pmx/importer.py | 1 + mmd_tools/operators/misc.py | 27 ++++++------------- 4 files changed, 52 insertions(+), 27 deletions(-) diff --git a/mmd_tools/__init__.py b/mmd_tools/__init__.py index 15bc13e7..c789b674 100644 --- a/mmd_tools/__init__.py +++ b/mmd_tools/__init__.py @@ -3,7 +3,7 @@ bl_info = { "name": "mmd_tools", "author": "sugiany", - "version": (2, 2, 3), + "version": (2, 2, 4), "blender": (2, 83, 0), "location": "View3D > Sidebar > MMD Tools Panel", "description": "Utility tools for MMD model editing. (UuuNyaa's forked version)", diff --git a/mmd_tools/core/model.py b/mmd_tools/core/model.py index cbcd353b..037f282b 100644 --- a/mmd_tools/core/model.py +++ b/mmd_tools/core/model.py @@ -249,27 +249,59 @@ def join_models(parent_root_object: bpy.types.Object, child_root_objects: List[b if len(child_root_object.children) == 0: bpy.data.objects.remove(child_root_object) -# SUPPORT_UNTIL: 4.3 LTS + @staticmethod + def _add_armature_modifier(mesh_object: bpy.types.Object, armature_object: bpy.types.Object) -> bpy.types.ArmatureModifier: + if any(m.type == 'ARMATURE' for m in mesh_object.modifiers): + # already has armature modifier. + return + + modifier: bpy.types.ArmatureModifier = mesh_object.modifiers.new(name='Armature', type='ARMATURE') + modifier.object = armature_object + modifier.use_vertex_groups = True + modifier.name = 'mmd_bone_order_override' + + return modifier + + @staticmethod + def attach_meshes(parent_root_object: bpy.types.Object, mesh_objects: Iterable[bpy.types.Object], add_armature_modifier: bool): + armature_object: bpy.types.Object = FnModel.find_armature(parent_root_object) + + def __get_root_object(obj: bpy.types.Object) -> bpy.types.Object: + if obj.parent is None: + return obj + return __get_root_object(obj.parent) + + for mesh_object in mesh_objects: + if mesh_object.type != 'MESH': + continue + if mesh_object.mmd_type != 'NONE': + continue + if FnModel.find_root(mesh_object) is not None: + continue + + mesh_root_object = __get_root_object(mesh_object) + original_matrix_world = mesh_root_object.matrix_world + mesh_root_object.parent_type = 'OBJECT' + mesh_root_object.parent = armature_object + mesh_root_object.matrix_world = original_matrix_world + + if add_armature_modifier: + FnModel._add_armature_modifier(mesh_object, armature_object) +# SUPPORT_UNTIL: 4.3 LTS def isRigidBodyObject(obj): return FnModel.is_rigid_body_object(obj) # SUPPORT_UNTIL: 4.3 LTS - - def isJointObject(obj): return FnModel.is_joint_object(obj) # SUPPORT_UNTIL: 4.3 LTS - - def isTemporaryObject(obj): return FnModel.is_temporary_object(obj) # SUPPORT_UNTIL: 4.3 LTS - - def getRigidBodySize(obj): return FnModel.get_rigid_body_size(obj) @@ -647,6 +679,9 @@ def meshes(self): return [] return FnModel.child_meshes(arm) + def attachMeshes(self, meshes: Iterable[bpy.types.Object], add_armature_modifier: bool = True): + FnModel.attach_meshes(self.rootObject(), meshes, add_armature_modifier) + def firstMesh(self): for i in self.meshes(): return i diff --git a/mmd_tools/core/pmx/importer.py b/mmd_tools/core/pmx/importer.py index 57af3364..d7a47998 100644 --- a/mmd_tools/core/pmx/importer.py +++ b/mmd_tools/core/pmx/importer.py @@ -774,6 +774,7 @@ def __importDisplayFrames(self): DisplayItemQuickSetup.apply_bone_groups(root.mmd_root, self.__armObj) def __addArmatureModifier(self, meshObj, armObj): + # TODO: move to model.py armModifier = meshObj.modifiers.new(name='Armature', type='ARMATURE') armModifier.object = armObj armModifier.use_vertex_groups = True diff --git a/mmd_tools/operators/misc.py b/mmd_tools/operators/misc.py index 7824ff5b..48a99eb9 100644 --- a/mmd_tools/operators/misc.py +++ b/mmd_tools/operators/misc.py @@ -230,33 +230,22 @@ class AttachMeshesToMMD(Operator): bl_description = 'Finds existing meshes and attaches them to the selected MMD model' bl_options = {'REGISTER', 'UNDO'} - def execute(self, context): - root = mmd_model.Model.findRoot(context.active_object) + add_armature_modifier: bpy.props.BoolProperty( + default=True + ) + + def execute(self, context: bpy.types.Context): + root = mmd_model.FnModel.find_root(context.active_object) if root is None: self.report({ 'ERROR' }, 'Select a MMD model') return { 'CANCELLED' } - rig = mmd_model.Model(root) - armObj = rig.armature() + armObj = mmd_model.FnModel.find_armature(root) if armObj is None: self.report({ 'ERROR' }, 'Model Armature not found') return { 'CANCELLED' } - def __get_root(mesh): - if mesh.parent is None: - return mesh - return __get_root(mesh.parent) - - meshes_list = (o for o in context.visible_objects if o.type == 'MESH' and o.mmd_type == 'NONE') - for mesh in meshes_list: - if mmd_model.Model.findRoot(mesh) is not None: - # Do not attach meshes from other models - continue - mesh = __get_root(mesh) - m = mesh.matrix_world - mesh.parent_type = 'OBJECT' - mesh.parent = armObj - mesh.matrix_world = m + mmd_model.FnModel.attach_meshes(root, context.visible_objects, self.add_armature_modifier) return { 'FINISHED' } class ChangeMMDIKLoopFactor(Operator):