PMX Import now works

This commit is contained in:
Yusarina
2025-04-10 23:40:51 +01:00
parent 3414ad8917
commit 69cc03098f
42 changed files with 12920 additions and 824 deletions
+87 -113
View File
@@ -1,41 +1,33 @@
# -*- coding: utf-8 -*-
# Copyright 2014 MMD Tools authors
# This file was originally part of the MMD Tools project, However Neoneko has added it to Avatar Toolkit.
# All credit goes to the original authors.
# Please note that some code was modified to fit the needs of Avatar Toolkit and some code may of been removed.
# MMD Tools is licensed under the terms of the GPL-3.0 license which Avatar Toolkit is also licensed under.
# You can find MMD Tools at: https://github.com/MMD-Blender/blender_mmd_tools/
# This file was originally part of the MMD Tools add-on for Blender
# You can find MMD Tools here: https://github.com/MMD-Blender/blender_mmd_tools
# Neoneko has modified this file to work with Avatar Toolkit and may of made changes or improvements.
# MMD Tools is licensed under the terms of the GNU General Public License version 3 (GPLv3) same as Avatar Toolkit.
from typing import cast
import bpy
from bpy.types import PropertyGroup, Context, PoseBone
from bpy.props import (
StringProperty,
IntProperty,
BoolProperty,
FloatProperty,
FloatVectorProperty
)
from ..logging_setup import logger
from ..bone import FnBone
from ..core.bone import FnBone
from . import patch_library_overridable
def _mmd_bone_update_additional_transform(prop, context: Context):
"""Update handler for additional transform properties"""
def _mmd_bone_update_additional_transform(prop: "MMDBone", context: bpy.types.Context):
prop["is_additional_transform_dirty"] = True
p_bone = context.active_pose_bone
if p_bone and p_bone.mmd_bone.as_pointer() == prop.as_pointer():
FnBone.apply_additional_transformation(prop.id_data)
def _mmd_bone_update_additional_transform_influence(prop, context: Context):
"""Update handler for additional transform influence"""
def _mmd_bone_update_additional_transform_influence(prop: "MMDBone", context: bpy.types.Context):
pose_bone = context.active_pose_bone
if pose_bone and pose_bone.mmd_bone.as_pointer() == prop.as_pointer():
FnBone.update_additional_transform_influence(pose_bone)
else:
prop["is_additional_transform_dirty"] = True
def _mmd_bone_get_additional_transform_bone(prop):
"""Getter for additional transform bone property"""
def _mmd_bone_get_additional_transform_bone(prop: "MMDBone"):
arm = prop.id_data
bone_id = prop.get("additional_transform_bone_id", -1)
if bone_id < 0:
@@ -45,8 +37,8 @@ def _mmd_bone_get_additional_transform_bone(prop):
return ""
return pose_bone.name
def _mmd_bone_set_additional_transform_bone(prop, value: str):
"""Setter for additional transform bone property"""
def _mmd_bone_set_additional_transform_bone(prop: "MMDBone", value: str):
arm = prop.id_data
prop["is_additional_transform_dirty"] = True
if value not in arm.pose.bones.keys():
@@ -55,85 +47,70 @@ def _mmd_bone_set_additional_transform_bone(prop, value: str):
pose_bone = arm.pose.bones[value]
prop["additional_transform_bone_id"] = FnBone.get_or_assign_bone_id(pose_bone)
def _pose_bone_update_mmd_ik_toggle(prop: PoseBone, _context):
"""Update handler for IK toggle property"""
v = prop.mmd_ik_toggle
armature_object = prop.id_data
for b in armature_object.pose.bones:
for c in b.constraints:
if c.type == "IK" and c.subtarget == prop.name:
logger.debug('Updating IK constraint %s on bone %s', c.name, b.name)
c.influence = v
b_chain = b if c.use_tail else b.parent
for chain_bone in ([b_chain] + b_chain.parent_recursive)[:c.chain_count]:
limit_c = next((c for c in chain_bone.constraints if c.type == "LIMIT_ROTATION" and not c.mute), None)
if limit_c:
limit_c.influence = v
class MMDBone(PropertyGroup):
"""Property group for MMD bone properties"""
name_j: StringProperty(
class MMDBone(bpy.types.PropertyGroup):
name_j: bpy.props.StringProperty(
name="Name",
description="Japanese Name",
default="",
)
name_e: StringProperty(
name_e: bpy.props.StringProperty(
name="Name(Eng)",
description="English Name",
default="",
)
bone_id: IntProperty(
bone_id: bpy.props.IntProperty(
name="Bone ID",
description="Unique ID for the reference of bone morph and rotate+/move+",
default=-1,
min=-1,
)
transform_order: IntProperty(
transform_order: bpy.props.IntProperty(
name="Transform Order",
description="Deformation tier",
min=0,
max=100,
soft_max=7,
)
is_controllable: BoolProperty(
is_controllable: bpy.props.BoolProperty(
name="Controllable",
description="Is controllable",
default=True,
)
transform_after_dynamics: BoolProperty(
transform_after_dynamics: bpy.props.BoolProperty(
name="After Dynamics",
description="After physics",
default=False,
)
enabled_fixed_axis: BoolProperty(
enabled_fixed_axis: bpy.props.BoolProperty(
name="Fixed Axis",
description="Use fixed axis",
default=False,
)
fixed_axis: FloatVectorProperty(
fixed_axis: bpy.props.FloatVectorProperty(
name="Fixed Axis",
description="Fixed axis",
subtype="XYZ",
size=3,
precision=3,
step=0.1,
step=0.1, # 0.1 / 100
default=[0, 0, 0],
)
enabled_local_axes: BoolProperty(
enabled_local_axes: bpy.props.BoolProperty(
name="Local Axes",
description="Use local axes",
default=False,
)
local_axis_x: FloatVectorProperty(
local_axis_x: bpy.props.FloatVectorProperty(
name="Local X-Axis",
description="Local x-axis",
subtype="XYZ",
@@ -142,8 +119,8 @@ class MMDBone(PropertyGroup):
step=0.1,
default=[1, 0, 0],
)
local_axis_z: FloatVectorProperty(
local_axis_z: bpy.props.FloatVectorProperty(
name="Local Z-Axis",
description="Local z-axis",
subtype="XYZ",
@@ -152,14 +129,14 @@ class MMDBone(PropertyGroup):
step=0.1,
default=[0, 0, 1],
)
is_tip: BoolProperty(
is_tip: bpy.props.BoolProperty(
name="Tip Bone",
description="Is zero length bone",
default=False,
)
ik_rotation_constraint: FloatProperty(
ik_rotation_constraint: bpy.props.FloatProperty(
name="IK Rotation Constraint",
description="The unit angle of IK",
subtype="ANGLE",
@@ -167,36 +144,36 @@ class MMDBone(PropertyGroup):
soft_max=4,
default=1,
)
has_additional_rotation: BoolProperty(
has_additional_rotation: bpy.props.BoolProperty(
name="Additional Rotation",
description="Additional rotation",
default=False,
update=_mmd_bone_update_additional_transform,
)
has_additional_location: BoolProperty(
has_additional_location: bpy.props.BoolProperty(
name="Additional Location",
description="Additional location",
default=False,
update=_mmd_bone_update_additional_transform,
)
additional_transform_bone: StringProperty(
additional_transform_bone: bpy.props.StringProperty(
name="Additional Transform Bone",
description="Additional transform bone",
set=_mmd_bone_set_additional_transform_bone,
get=_mmd_bone_get_additional_transform_bone,
update=_mmd_bone_update_additional_transform,
)
additional_transform_bone_id: IntProperty(
additional_transform_bone_id: bpy.props.IntProperty(
name="Additional Transform Bone ID",
default=-1,
update=_mmd_bone_update_additional_transform,
)
additional_transform_influence: FloatProperty(
additional_transform_influence: bpy.props.FloatProperty(
name="Additional Transform Influence",
description="Additional transform influence",
default=1,
@@ -204,47 +181,44 @@ class MMDBone(PropertyGroup):
soft_max=1,
update=_mmd_bone_update_additional_transform_influence,
)
is_additional_transform_dirty: BoolProperty(
name="",
default=True
)
is_additional_transform_dirty: bpy.props.BoolProperty(name="", default=True)
def is_id_unique(self):
"""Check if the bone ID is unique"""
return self.bone_id < 0 or not next((b for b in self.id_data.pose.bones if b.mmd_bone != self and b.mmd_bone.bone_id == self.bone_id), None)
@staticmethod
def register():
bpy.types.PoseBone.mmd_bone = patch_library_overridable(bpy.props.PointerProperty(type=MMDBone))
bpy.types.PoseBone.is_mmd_shadow_bone = patch_library_overridable(bpy.props.BoolProperty(name="is_mmd_shadow_bone", default=False))
bpy.types.PoseBone.mmd_shadow_bone_type = patch_library_overridable(bpy.props.StringProperty(name="mmd_shadow_bone_type"))
bpy.types.PoseBone.mmd_ik_toggle = patch_library_overridable(
bpy.props.BoolProperty(
name="MMD IK Toggle",
description="MMD IK toggle is used to import/export animation of IK on-off",
update=_pose_bone_update_mmd_ik_toggle,
default=True,
)
)
def register():
"""Register MMD bone properties"""
logger.info("Registering MMD bone properties")
bpy.utils.register_class(MMDBone)
# Add properties to PoseBone
bpy.types.PoseBone.mmd_bone = bpy.props.PointerProperty(type=MMDBone)
bpy.types.PoseBone.is_mmd_shadow_bone = bpy.props.BoolProperty(
name="is_mmd_shadow_bone",
default=False
)
bpy.types.PoseBone.mmd_shadow_bone_type = bpy.props.StringProperty(
name="mmd_shadow_bone_type"
)
bpy.types.PoseBone.mmd_ik_toggle = bpy.props.BoolProperty(
name="MMD IK Toggle",
description="MMD IK toggle is used to import/export animation of IK on-off",
update=_pose_bone_update_mmd_ik_toggle,
default=True,
)
@staticmethod
def unregister():
del bpy.types.PoseBone.mmd_ik_toggle
del bpy.types.PoseBone.mmd_shadow_bone_type
del bpy.types.PoseBone.is_mmd_shadow_bone
del bpy.types.PoseBone.mmd_bone
def unregister():
"""Unregister MMD bone properties"""
logger.info("Unregistering MMD bone properties")
# Remove properties from PoseBone
del bpy.types.PoseBone.mmd_ik_toggle
del bpy.types.PoseBone.mmd_shadow_bone_type
del bpy.types.PoseBone.is_mmd_shadow_bone
del bpy.types.PoseBone.mmd_bone
bpy.utils.unregister_class(MMDBone)
def _pose_bone_update_mmd_ik_toggle(prop: bpy.types.PoseBone, _context):
v = prop.mmd_ik_toggle
armature_object = cast(bpy.types.Object, prop.id_data)
for b in armature_object.pose.bones:
for c in b.constraints:
if c.type == "IK" and c.subtarget == prop.name:
# logging.debug(' %s %s', b.name, c.name)
c.influence = v
b = b if c.use_tail else b.parent
for b in ([b] + b.parent_recursive)[: c.chain_count]:
c = next((c for c in b.constraints if c.type == "LIMIT_ROTATION" and not c.mute), None)
if c:
c.influence = v