diff --git a/core/common.py b/core/common.py index 6b060f9..14e4914 100644 --- a/core/common.py +++ b/core/common.py @@ -119,12 +119,49 @@ def get_armatures_that_are_not_selected(self, context: Context) -> List[Tuple[st return [(obj.name, obj.name, "") for obj in bpy.data.objects if ((obj.type == 'ARMATURE') and (obj.name != context.scene.selected_armature))] def get_selected_armature(context: Context) -> Optional[Object]: - if context.scene.selected_armature: - armature = bpy.data.objects.get(context.scene.selected_armature) - if is_valid_armature(armature): - return armature + try: + if hasattr(context.scene, 'selected_armature'): + armature_name = context.scene.selected_armature + if isinstance(armature_name, bytes): + try: + armature_name = armature_name.decode('utf-8') + except UnicodeDecodeError: + try: + armature_name = armature_name.decode('gbk') # For Chinese characters + except UnicodeDecodeError: + try: + armature_name = armature_name.decode('shift-jis') + except UnicodeDecodeError: + armature_name = armature_name.decode('latin1') + + if armature_name: + armature = bpy.data.objects.get(str(armature_name)) + if is_valid_armature(armature): + return armature + except Exception: + pass return None +def get_merge_armature_source(context: Context) -> Optional[Object]: + try: + if hasattr(context.scene, 'merge_armature_source'): + source_name = context.scene.merge_armature_source + if isinstance(source_name, bytes): + try: + source_name = source_name.decode('utf-8') + except UnicodeDecodeError: + try: + source_name = source_name.decode('shift-jis') + except UnicodeDecodeError: + source_name = source_name.decode('latin1', errors='ignore') + + if source_name: + return bpy.data.objects.get(str(source_name)) + except Exception: + pass + return None + + def set_selected_armature(context: Context, armature: Optional[Object]) -> None: context.scene.selected_armature = armature.name if armature else "" diff --git a/core/import_pmx.py b/core/import_pmx.py index c0640b6..33865bc 100644 --- a/core/import_pmx.py +++ b/core/import_pmx.py @@ -521,6 +521,19 @@ def setup_physics(obj: bpy.types.Object, armature_obj: bpy.types.Object, rigid_b constraint.limit_ang_z_upper = joint.angular_limit_max[2] def create_armature(model_name: str, bones: list[PMXBone]) -> bpy.types.Object: + # Handle CJK characters in model name + if isinstance(model_name, bytes): + try: + model_name = model_name.decode('gbk') # Try Chinese encoding first + except UnicodeDecodeError: + try: + model_name = model_name.decode('utf-8') + except UnicodeDecodeError: + try: + model_name = model_name.decode('shift-jis') + except UnicodeDecodeError: + model_name = model_name.decode('latin1') + armature = bpy.data.armatures.new(f"{model_name}_Armature") armature_obj = bpy.data.objects.new(f"{model_name}_Armature", armature) bpy.context.collection.objects.link(armature_obj) @@ -602,7 +615,6 @@ def create_armature(model_name: str, bones: list[PMXBone]) -> bpy.types.Object: edit_bones.append(edit_bone) - # Second pass: Set up hierarchy and orientations for i, bone_data in enumerate(bones): edit_bone = edit_bones[i] @@ -625,14 +637,14 @@ def create_armature(model_name: str, bones: list[PMXBone]) -> bpy.types.Object: y_axis = z_axis.cross(x_axis) # Create and apply orientation matrix - matrix = Matrix((x_axis, y_axis, z_axis)).to_3x3() - edit_bone.matrix = matrix + matrix_3x3 = Matrix((x_axis, y_axis, z_axis)).to_3x3() + matrix_4x4 = matrix_3x3.to_4x4() + edit_bone.matrix = matrix_4x4 bpy.ops.object.mode_set(mode='OBJECT') return armature_obj - def assign_vertex_weights(obj: bpy.types.Object, vertices: list[PMXVertex], bones: list[PMXBone]): # Pre-create vertex groups vertex_groups = {} diff --git a/functions/armature_modifying.py b/functions/armature_modifying.py index 34fde6b..2797cc7 100644 --- a/functions/armature_modifying.py +++ b/functions/armature_modifying.py @@ -264,8 +264,8 @@ class AvatarToolkit_OT_MergeArmatures(Operator): bl_options = {'REGISTER', 'UNDO'} @classmethod - def poll(cls, context: Context) -> bool: - return (common.get_selected_armature(context) is not None) and (context.scene.merge_armature_source is not None) + def poll(cls, context): + return (common.get_selected_armature(context) is not None) and (common.get_merge_armature_source(context) is not None) def make_active(self, obj: bpy.types.Object, context: Context): context.view_layer.objects.active = obj