feat(importing): Add better FBX bone orientations operator and accessory bone deletion
- Add new `apply_better_fbx_orientations` operator as standalone UI action for applying bone orientations - Add "Delete Accessory Bones" property and UI toggle in EXTRAS panel for optional bone cleanup - Move bone orientation logic from `modify_armature` execute method to new dedicated operator - Refactor accessory bone deletion into separate method callable from new operator - Update panel UI to show better FBX bones operator with delete accessory bones toggle option - Register new operator in `__init__.py` and export from modifyarmature module - Update interface dictionaries (English, Japanese, Chinese) with new UI strings - Enable better FBX orientations and accessory deletion only for Koikatsu armature (C) selection - Add detailed logging for bone operation counts and status tracking
This commit is contained in:
@@ -346,9 +346,6 @@ class modify_armature(bpy.types.Operator):
|
||||
self.categorize_bones()
|
||||
self.rename_bones_for_clarity()
|
||||
self.rename_mmd_bones()
|
||||
|
||||
# 最后再次应用 better_fbx 骨骼方向,确保不被其他步骤覆盖
|
||||
self.apply_better_fbx_bone_orientations()
|
||||
|
||||
self.apply_bone_widgets()
|
||||
self.hide_widgets()
|
||||
@@ -488,10 +485,6 @@ class modify_armature(bpy.types.Operator):
|
||||
bpy.ops.armature.select_all(action='INVERT')
|
||||
bpy.ops.armature.delete()
|
||||
|
||||
# 只在选择 Koikatsu armature (C) 时删除配饰骨骼
|
||||
if bpy.context.scene.kkbp.armature_dropdown == 'C':
|
||||
self.delete_accessory_bones()
|
||||
|
||||
c.print_timer('delete_non_height_bones')
|
||||
|
||||
def delete_accessory_bones(self):
|
||||
@@ -1208,35 +1201,7 @@ class modify_armature(bpy.types.Operator):
|
||||
armature.pose.bones[pmx_rename_dict[bone]].mmd_bone.name_j = bone
|
||||
c.print_timer('rename_mmd_bones')
|
||||
|
||||
def apply_better_fbx_bone_orientations(self):
|
||||
'''统一应用 better_fbx 骨骼方向,确保不被其他步骤覆盖 (仅在选择 Koikatsu armature 时)'''
|
||||
# 只在选择 Koikatsu armature (C) 时应用 better_fbx 骨骼方向
|
||||
if bpy.context.scene.kkbp.armature_dropdown != 'C':
|
||||
c.print_timer('apply_better_fbx_bone_orientations (skipped)')
|
||||
return
|
||||
|
||||
armature = c.get_armature()
|
||||
c.switch(armature, 'edit')
|
||||
|
||||
applied_count = 0
|
||||
skipped_count = 0
|
||||
|
||||
print("[KKBP] 应用 better_fbx 骨骼方向...")
|
||||
|
||||
# 遍历字典中的所有骨骼并应用方向
|
||||
for bone_name, offset in better_fbx_bone_tails.items():
|
||||
if bone_name in armature.data.edit_bones:
|
||||
bone = armature.data.edit_bones[bone_name]
|
||||
bone.tail = bone.head + Vector(offset)
|
||||
applied_count += 1
|
||||
else:
|
||||
skipped_count += 1
|
||||
|
||||
print(f"[KKBP] 骨骼方向应用完成: {applied_count} 个已应用, {skipped_count} 个跳过")
|
||||
print(f"[KKBP] 骨架总骨骼数: {len(armature.data.edit_bones)}")
|
||||
|
||||
c.switch(armature, 'object')
|
||||
c.print_timer('apply_better_fbx_bone_orientations')
|
||||
|
||||
|
||||
def visually_connect_bones(self):
|
||||
'''make sure certain bones are visually connected'''
|
||||
@@ -2365,3 +2330,91 @@ class modify_armature(bpy.types.Operator):
|
||||
bone = c.get_armature().data.edit_bones.new(new_bone_name)
|
||||
return bone
|
||||
|
||||
|
||||
|
||||
class apply_better_fbx_orientations(bpy.types.Operator):
|
||||
bl_idname = "kkbp.applybetterfbxorientations"
|
||||
bl_label = "应用 Better FBX 骨骼方向"
|
||||
bl_description = "将骨骼方向修改为更自然的方向(基于 better_fbx 数据)。这会让骨骼沿着肢体方向延伸,而不是都朝上"
|
||||
bl_options = {'REGISTER', 'UNDO'}
|
||||
|
||||
def execute(self, context):
|
||||
try:
|
||||
armature = c.get_armature()
|
||||
if not armature:
|
||||
self.report({'ERROR'}, "未找到骨架对象")
|
||||
return {'CANCELLED'}
|
||||
|
||||
c.switch(armature, 'edit')
|
||||
|
||||
# 记录删除前的骨骼数量
|
||||
bones_before = len(armature.data.edit_bones)
|
||||
print(f"[KKBP] 操作前骨骼数量: {bones_before}")
|
||||
|
||||
# 如果勾选了删除配饰骨骼选项,先删除配饰骨骼
|
||||
delete_option = context.scene.kkbp.delete_accessory_bones
|
||||
print(f"[KKBP] 删除配饰骨骼选项: {delete_option}")
|
||||
|
||||
if delete_option:
|
||||
print("[KKBP] 开始删除配饰骨骼...")
|
||||
self.delete_accessory_bones(armature)
|
||||
bones_after_delete = len(armature.data.edit_bones)
|
||||
print(f"[KKBP] 删除后骨骼数量: {bones_after_delete}")
|
||||
else:
|
||||
print("[KKBP] 跳过删除配饰骨骼")
|
||||
|
||||
applied_count = 0
|
||||
skipped_count = 0
|
||||
|
||||
print("[KKBP] 应用 better_fbx 骨骼方向...")
|
||||
|
||||
# 遍历字典中的所有骨骼并应用方向
|
||||
for bone_name, offset in better_fbx_bone_tails.items():
|
||||
if bone_name in armature.data.edit_bones:
|
||||
bone = armature.data.edit_bones[bone_name]
|
||||
bone.tail = bone.head + Vector(offset)
|
||||
applied_count += 1
|
||||
else:
|
||||
skipped_count += 1
|
||||
|
||||
c.switch(armature, 'object')
|
||||
|
||||
self.report({'INFO'}, f"骨骼方向应用完成: {applied_count} 个已应用, {skipped_count} 个跳过")
|
||||
print(f"[KKBP] 骨骼方向应用完成: {applied_count} 个已应用, {skipped_count} 个跳过")
|
||||
print(f"[KKBP] 骨架总骨骼数: {len(armature.data.edit_bones)}")
|
||||
|
||||
return {'FINISHED'}
|
||||
except Exception as error:
|
||||
c.handle_error(self, error)
|
||||
return {"CANCELLED"}
|
||||
|
||||
def delete_accessory_bones(self, armature):
|
||||
'''删除不在 better_fbx_bone_tails 字典中的骨骼,只保留核心人体骨骼(仅用于 C 模式)'''
|
||||
# 定义必须保留的骨骼(即使不在 better_fbx_bone_tails 中)
|
||||
must_keep_bones = [
|
||||
'cf_hit_head', # 头部碰撞
|
||||
'p_cf_body_bone', # 身体骨骼
|
||||
'p_cf_head_bone', # 头部骨骼
|
||||
'a_n_back', # 背部锚点
|
||||
'a_n_headside', # 头部侧面锚点
|
||||
'cf_J_hitomi_tx_R', # 右眼瞳控制
|
||||
'cf_J_hitomi_tx_L', # 左眼瞳控制
|
||||
]
|
||||
|
||||
# 收集所有需要删除的骨骼(不在 better_fbx_bone_tails 中且不在必须保留列表中的)
|
||||
bones_to_delete = []
|
||||
for bone in armature.data.edit_bones:
|
||||
bone_name = bone.name
|
||||
# 如果骨骼不在 better_fbx_bone_tails 字典中,且不在必须保留列表中,标记为删除
|
||||
if bone_name not in better_fbx_bone_tails and bone_name not in must_keep_bones:
|
||||
bones_to_delete.append(bone_name)
|
||||
|
||||
# 删除标记的骨骼
|
||||
deleted_count = 0
|
||||
for bone_name in bones_to_delete:
|
||||
if bone_name in armature.data.edit_bones:
|
||||
armature.data.edit_bones.remove(armature.data.edit_bones[bone_name])
|
||||
deleted_count += 1
|
||||
|
||||
print(f"[KKBP] 已删除 {deleted_count} 个配饰骨骼(包括 IK 控制骨骼)")
|
||||
print(f"[KKBP] 保留了 {len(better_fbx_bone_tails)} 个核心骨骼 + {len(must_keep_bones)} 个必需骨骼")
|
||||
|
||||
Reference in New Issue
Block a user