feat(body_mesh): Add edge UV data for facial and hair mesh components

- Add edge UV coordinate data for N00_000_00_FaceEyelash_00_FACE mesh instance with 112 edges
- Add edge UV coordinate data for N00_000_00_HairBack_00_HAIR mesh instance with 800 edges
- Update body_mesh module initialization and operations to support new mesh data
- Enhance panel UI and utility functions for mesh edge UV handling
- Add comprehensive UV matching test suite for validation
- Update registration module to include new mesh components
- Improve test utilities for edge UV data verification
This commit is contained in:
2026-01-02 13:32:03 +08:00
parent f2257449de
commit 21222044c4
10 changed files with 10147 additions and 58 deletions

View File

@@ -7,8 +7,9 @@ from bpy.types import Context, Panel
from .utils import (
MaterialInfo,
find_body_mesh,
find_face_mesh,
get_material_face_count,
is_skin_material,
is_retained_material,
)
if TYPE_CHECKING:
@@ -69,45 +70,64 @@ class VRM_PT_body_mesh_separator(Panel):
layout.label(text="Body网格数据无效", icon="ERROR")
return
# 显示材质统计信息
# 显示材质统计信息(区分保留材质和可分离材质)
box = layout.box()
box.label(text="材质列表", icon="MATERIAL")
# 收集材质信息
# 收集材质信息使用is_retained_material和is_separable_material分类
materials_info: list[MaterialInfo] = []
for i, material in enumerate(mesh_data.materials):
if material is not None:
face_count = get_material_face_count(mesh_data, i)
is_skin = is_skin_material(material.name)
is_retained = is_retained_material(material.name)
materials_info.append(
MaterialInfo(
name=material.name,
index=i,
face_count=face_count,
is_skin=is_skin,
is_skin=is_retained, # 使用is_skin字段存储保留状态
)
)
# 显示材质列表
has_non_skin = False
# 显示材质列表区分保留材质SKIN/HAIR和可分离材质CLOTH和其他
has_separable = False
for mat_info in materials_info:
row = box.row()
if mat_info.is_skin:
row.label(text=f"[皮肤] {mat_info.name}", icon="CHECKMARK")
if mat_info.is_skin: # is_skin字段现在表示是否为保留材质
# 保留材质SKIN/HAIR标记为"[保留]"
row.label(text=f"[保留] {mat_info.name}", icon="CHECKMARK")
else:
row.label(text=f"[非皮肤] {mat_info.name}", icon="MESH_DATA")
has_non_skin = True
# 可分离材质CLOTH和其他标记为"[分离]"
row.label(text=f"[分离] {mat_info.name}", icon="MESH_DATA")
has_separable = True
row.label(text=f"{mat_info.face_count}")
# 显示分离操作按钮
layout.separator()
col = layout.column()
col.enabled = has_non_skin
col.enabled = has_separable
col.operator(
"vrm.separate_non_skin_faces",
text="分离非皮肤面",
icon="MESH_DATA",
)
if not has_non_skin:
layout.label(text="没有非皮肤材质可分离", icon="INFO")
if not has_separable:
layout.label(text="没有可分离材质", icon="INFO")
# 显示UV边融并按钮 (Requirements 1.2, 1.3)
layout.separator()
armature = self._get_armature(context)
face_mesh = find_face_mesh(armature) if armature else None
has_vrm_structure = body_mesh is not None and face_mesh is not None
col = layout.column()
col.enabled = has_vrm_structure
col.operator(
"vrm.merge_uv_edges",
text="根据UV转四边面",
icon="MOD_EDGESPLIT",
)
if not has_vrm_structure:
layout.label(text="需要Body和Face网格", icon="INFO")