This commit is contained in:
2025-05-06 00:34:14 +08:00
parent dd54de1bfa
commit d2f182ef36
2 changed files with 404 additions and 243 deletions

View File

@@ -91,40 +91,19 @@ class GeometryUI(ui_utils.BaseUI):
self.controls["title_label"].setAlignment(QtCore.Qt.AlignCenter)
self.controls["title_label"].setMaximumHeight(30) # 限制标题高度
# 左侧面板
self.controls["left_panel"] = QtWidgets.QWidget()
self.controls["left_panel"].setObjectName("geometryLeftPanel")
# 创建主容器
self.controls["main_container"] = QtWidgets.QWidget()
self.controls["main_container"].setObjectName("geometryMainContainer")
# 右侧面板
self.controls["right_panel"] = QtWidgets.QWidget()
self.controls["right_panel"].setObjectName("geometryRightPanel")
# 创建标签页控件
self.controls["tab_widget"] = QtWidgets.QTabWidget()
self.controls["tab_widget"].setObjectName("geometryTabWidget")
# 左侧面板控件 - LOD列表
self.controls["lod_group"] = QtWidgets.QGroupBox("LOD [000]")
self.controls["lod_group"].setObjectName("lodGroup")
# 创建LOD标签页
self.create_lod_tabs()
# LOD列表
self.controls["lod_list"] = QtWidgets.QListWidget()
self.controls["lod_list"].setObjectName("lodList")
# 添加测试项目
for i in range(4):
item = QtWidgets.QListWidgetItem(f"LOD{i}")
self.controls["lod_list"].addItem(item)
# LOD操作按钮
self.buttons["add_lod"] = QtWidgets.QPushButton(LANG.get("add_lod", "添加LOD"))
self.buttons["add_lod"].setObjectName("addLodButton")
self.buttons["remove_lod"] = QtWidgets.QPushButton(LANG.get("remove_lod", "移除LOD"))
self.buttons["remove_lod"].setObjectName("removeLodButton")
self.buttons["duplicate_lod"] = QtWidgets.QPushButton(LANG.get("duplicate_lod", "复制LOD"))
self.buttons["duplicate_lod"].setObjectName("duplicateLodButton")
# 左侧面板控件 - 模型列表
self.controls["model_group"] = QtWidgets.QGroupBox("Models [000]")
self.controls["model_group"].setObjectName("modelGroup")
# 创建底部功能按钮区域
self.create_bottom_buttons()
# 模型列表
self.controls["model_list"] = QtWidgets.QListWidget()
@@ -235,6 +214,172 @@ class GeometryUI(ui_utils.BaseUI):
self.buttons["uv_tools"] = QtWidgets.QPushButton(LANG.get("uv_tools", "UV工具"))
self.buttons["uv_tools"].setObjectName("uvToolsButton")
def create_lod_tabs(self):
"""
创建LOD标签页
包括LOD0~LOD7的标签页
"""
# 创建8个LOD标签页
lod_names = [f"LOD{i}" for i in range(8)]
# 创建标签页和内容
for lod_name in lod_names:
# 创建标签页
tab = QtWidgets.QWidget()
tab.setObjectName(f"{lod_name}Tab")
# 创建标签页布局
tab_layout = QtWidgets.QVBoxLayout(tab)
tab_layout.setContentsMargins(5, 5, 5, 5)
tab_layout.setSpacing(5)
# 创建身体部位输入字段
body_parts = [
"头部", "牙齿", "牙龈", "左眼", "右眼", "红脸", "眉毛", "眉毛", "躯体"
]
# 根据LOD级别限制显示的身体部位
if lod_name in ["LOD0", "LOD1"]:
parts_to_show = body_parts
elif lod_name in ["LOD2", "LOD3"]:
parts_to_show = body_parts[:8]
elif lod_name in ["LOD4", "LOD5"]:
parts_to_show = body_parts[:5]
else: # LOD6, LOD7
parts_to_show = body_parts[:4]
# 为每个身体部位创建输入字段和加载按钮
for part in parts_to_show:
# 创建水平布局
part_layout = QtWidgets.QHBoxLayout()
part_layout.setSpacing(5)
# 创建标签
label = QtWidgets.QLabel(f"{part}:")
label.setMinimumWidth(40)
label.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
# 创建输入字段
input_field = QtWidgets.QLineEdit()
input_field.setObjectName(f"{lod_name}_{part}_input")
input_field.setPlaceholderText(LANG.get("enter_model_name", "输入模型名称"))
# 创建加载按钮
load_button = QtWidgets.QPushButton(LANG.get("load", "加载"))
load_button.setObjectName(f"{lod_name}_{part}_load_button")
load_button.setIcon(QtGui.QIcon(os.path.join(ICONS_PATH, "loading.png")))
load_button.setFixedSize(60, 24) # 增加宽度以容纳文字
load_button.setToolTip(LANG.get("load_model", "加载模型"))
# 将控件添加到布局
part_layout.addWidget(label)
part_layout.addWidget(input_field)
part_layout.addWidget(load_button)
# 将布局添加到标签页布局
tab_layout.addLayout(part_layout)
# 保存控件引用
self.controls[f"{lod_name}_{part}_label"] = label
self.controls[f"{lod_name}_{part}_input"] = input_field
self.buttons[f"{lod_name}_{part}_load"] = load_button
# 添加弹性空间
tab_layout.addStretch(1)
# 将标签页添加到标签页控件
self.controls["tab_widget"].addTab(tab, lod_name)
# 添加垃圾桶按钮到标签页控件右侧
trash_icon = QtGui.QIcon(os.path.join(ICONS_PATH, "delete.png"))
trash_button = QtWidgets.QPushButton()
trash_button.setIcon(trash_icon)
trash_button.setIconSize(QtCore.QSize(32, 32)) # 设置图标大小为32x32
trash_button.setFixedSize(32, 32) # 增大按钮尺寸
trash_button.setToolTip(LANG.get("delete", "删除"))
trash_button.setStyleSheet("QPushButton { border: none; background-color: transparent; }")
self.controls["tab_widget"].setCornerWidget(trash_button, QtCore.Qt.TopRightCorner)
self.buttons["delete"] = trash_button
def create_bottom_buttons(self):
"""
创建底部功能按钮区域
包括自动化模型、标准化名称、自动分组等功能按钮
"""
# 创建底部功能区域
self.controls["bottom_area"] = QtWidgets.QWidget()
self.controls["bottom_area"].setObjectName("geometryBottomArea")
self.controls["bottom_area"].setMinimumHeight(150)
self.controls["bottom_area"].setMaximumHeight(200)
# 创建底部区域布局
bottom_layout = QtWidgets.QVBoxLayout(self.controls["bottom_area"])
bottom_layout.setContentsMargins(5, 5, 5, 5)
bottom_layout.setSpacing(5)
# 创建三个功能按钮组
button_group_layout = QtWidgets.QHBoxLayout()
button_group_layout.setSpacing(5)
# 自动化模型按钮
self.buttons["auto_model"] = QtWidgets.QPushButton()
self.buttons["auto_model"].setIcon(QtGui.QIcon(os.path.join(ICONS_PATH, "load_meshes.png")))
self.buttons["auto_model"].setText(LANG.get("auto_model", "自动化模型"))
self.buttons["auto_model"].setObjectName("autoModelButton")
self.buttons["auto_model"].setMinimumHeight(40)
# 标准化名称按钮
self.buttons["standardize_names"] = QtWidgets.QPushButton()
self.buttons["standardize_names"].setIcon(QtGui.QIcon(os.path.join(ICONS_PATH, "standardized_naming.png")))
self.buttons["standardize_names"].setText(LANG.get("standardize_names", "标准化名称"))
self.buttons["standardize_names"].setObjectName("standardizeNamesButton")
self.buttons["standardize_names"].setMinimumHeight(40)
# 自动分组按钮
self.buttons["auto_group"] = QtWidgets.QPushButton()
self.buttons["auto_group"].setIcon(QtGui.QIcon(os.path.join(ICONS_PATH, "automatic_grouping.png")))
self.buttons["auto_group"].setText(LANG.get("auto_group", "自动分组"))
self.buttons["auto_group"].setObjectName("autoGroupButton")
self.buttons["auto_group"].setMinimumHeight(40)
# 添加按钮到布局
button_group_layout.addWidget(self.buttons["auto_model"])
button_group_layout.addWidget(self.buttons["standardize_names"])
button_group_layout.addWidget(self.buttons["auto_group"])
# 创建模型工具区域
model_tools_group = QtWidgets.QGroupBox(LANG.get("model_tools", "模型工具"))
model_tools_group.setObjectName("modelToolsGroup")
# 创建模型工具布局
model_tools_layout = QtWidgets.QGridLayout(model_tools_group)
model_tools_layout.setContentsMargins(5, 5, 5, 5)
model_tools_layout.setSpacing(5)
# 创建模型工具按钮
tool_buttons = [
{"name": "modify_topology", "text": LANG.get("modify_topology", "修改拓扑"), "icon": "topology_distribution.png", "row": 0, "col": 0},
{"name": "fix_seams", "text": LANG.get("fix_seams", "修复接缝"), "icon": "fix_seams.png", "row": 0, "col": 1},
{"name": "generate_face_components", "text": LANG.get("generate_face_components", "生成面部配件"), "icon": "generate_facial_components.png", "row": 0, "col": 2},
{"name": "fix_vertex_order", "text": LANG.get("fix_vertex_order", "修复点序"), "icon": "fix_vertex_order.png", "row": 1, "col": 0},
{"name": "optimize_model", "text": LANG.get("optimize_model", "优化模型"), "icon": "optimize_model.png", "row": 1, "col": 1},
{"name": "generate_uvs", "text": LANG.get("generate_uvs", "生成UVs"), "icon": "generate_uvs.png", "row": 1, "col": 2}
]
# 创建并添加按钮到布局
for btn_info in tool_buttons:
button = QtWidgets.QPushButton()
button.setText(btn_info["text"])
button.setIcon(QtGui.QIcon(os.path.join(ICONS_PATH, btn_info["icon"])))
button.setObjectName(f"{btn_info['name']}Button")
button.setMinimumHeight(30)
model_tools_layout.addWidget(button, btn_info["row"], btn_info["col"])
self.buttons[btn_info["name"]] = button
# 添加布局到底部区域
bottom_layout.addLayout(button_group_layout)
bottom_layout.addWidget(model_tools_group)
#========================================= LAYOUT =======================================
def create_layouts(self):
"""
@@ -243,180 +388,17 @@ class GeometryUI(ui_utils.BaseUI):
"""
# 主布局
self.layouts["main_layout"] = QtWidgets.QVBoxLayout(self.main_widget)
self.layouts["main_layout"].setContentsMargins(2, 2, 2, 2)
self.layouts["main_layout"].setSpacing(2)
self.layouts["main_layout"].setContentsMargins(0, 0, 0, 0)
self.layouts["main_layout"].setSpacing(0)
# 添加标题标签
self.layouts["main_layout"].addWidget(self.controls["title_label"])
# 创建主分割器
self.splitters["main_splitter"] = QtWidgets.QSplitter(QtCore.Qt.Horizontal)
self.splitters["main_splitter"].setObjectName("geometryMainSplitter")
self.layouts["main_layout"].addWidget(self.splitters["main_splitter"])
# 添加标签页控件到主布局
self.layouts["main_layout"].addWidget(self.controls["tab_widget"])
# 左侧面板布局
self.layouts["left_layout"] = QtWidgets.QVBoxLayout(self.controls["left_panel"])
self.layouts["left_layout"].setContentsMargins(5, 5, 5, 5)
self.layouts["left_layout"].setSpacing(5)
# LOD组布局
self.layouts["lod_group_layout"] = QtWidgets.QVBoxLayout(self.controls["lod_group"])
self.layouts["lod_group_layout"].setContentsMargins(5, 10, 5, 5)
self.layouts["lod_group_layout"].setSpacing(5)
# LOD列表
self.layouts["lod_group_layout"].addWidget(self.controls["lod_list"])
# LOD操作按钮行
self.layouts["lod_buttons_layout"] = QtWidgets.QHBoxLayout()
self.layouts["lod_buttons_layout"].setContentsMargins(0, 0, 0, 0)
self.layouts["lod_buttons_layout"].setSpacing(2)
self.layouts["lod_buttons_layout"].addWidget(self.buttons["add_lod"])
self.layouts["lod_buttons_layout"].addWidget(self.buttons["remove_lod"])
self.layouts["lod_buttons_layout"].addWidget(self.buttons["duplicate_lod"])
self.layouts["lod_group_layout"].addLayout(self.layouts["lod_buttons_layout"])
# 模型组布局
self.layouts["model_group_layout"] = QtWidgets.QVBoxLayout(self.controls["model_group"])
self.layouts["model_group_layout"].setContentsMargins(5, 10, 5, 5)
self.layouts["model_group_layout"].setSpacing(5)
# 模型列表
self.layouts["model_group_layout"].addWidget(self.controls["model_list"])
# 模型操作按钮行
self.layouts["model_buttons_layout"] = QtWidgets.QHBoxLayout()
self.layouts["model_buttons_layout"].setContentsMargins(0, 0, 0, 0)
self.layouts["model_buttons_layout"].setSpacing(2)
self.layouts["model_buttons_layout"].addWidget(self.buttons["add_model"])
self.layouts["model_buttons_layout"].addWidget(self.buttons["remove_model"])
self.layouts["model_buttons_layout"].addWidget(self.buttons["duplicate_model"])
self.layouts["model_group_layout"].addLayout(self.layouts["model_buttons_layout"])
# 添加组到左侧面板
self.layouts["left_layout"].addWidget(self.controls["lod_group"])
self.layouts["left_layout"].addWidget(self.controls["model_group"])
# 右侧面板布局
self.layouts["right_layout"] = QtWidgets.QVBoxLayout(self.controls["right_panel"])
self.layouts["right_layout"].setContentsMargins(5, 5, 5, 5)
self.layouts["right_layout"].setSpacing(5)
# 模型属性组布局
self.layouts["model_properties_layout"] = QtWidgets.QVBoxLayout(self.controls["model_properties_group"])
self.layouts["model_properties_layout"].setContentsMargins(5, 10, 5, 5)
self.layouts["model_properties_layout"].setSpacing(5)
# 模型名称行
self.layouts["model_name_layout"] = QtWidgets.QHBoxLayout()
self.layouts["model_name_layout"].setContentsMargins(0, 0, 0, 0)
self.layouts["model_name_layout"].setSpacing(5)
self.layouts["model_name_layout"].addWidget(self.controls["model_name_label"])
self.layouts["model_name_layout"].addWidget(self.controls["model_name_input"])
self.layouts["model_properties_layout"].addLayout(self.layouts["model_name_layout"])
# 模型类型行
self.layouts["model_type_layout"] = QtWidgets.QHBoxLayout()
self.layouts["model_type_layout"].setContentsMargins(0, 0, 0, 0)
self.layouts["model_type_layout"].setSpacing(5)
self.layouts["model_type_layout"].addWidget(self.controls["model_type_label"])
self.layouts["model_type_layout"].addWidget(self.controls["model_type_combo"])
self.layouts["model_properties_layout"].addLayout(self.layouts["model_type_layout"])
# 可见性复选框
self.layouts["model_properties_layout"].addWidget(self.controls["model_visible_check"])
# 属性按钮行
self.layouts["properties_buttons_layout"] = QtWidgets.QHBoxLayout()
self.layouts["properties_buttons_layout"].setContentsMargins(0, 0, 0, 0)
self.layouts["properties_buttons_layout"].setSpacing(5)
self.layouts["properties_buttons_layout"].addWidget(self.buttons["apply_properties"])
self.layouts["properties_buttons_layout"].addWidget(self.buttons["reset_properties"])
self.layouts["model_properties_layout"].addLayout(self.layouts["properties_buttons_layout"])
# 模型工具组布局
self.layouts["model_tools_layout"] = QtWidgets.QVBoxLayout(self.controls["model_tools_group"])
self.layouts["model_tools_layout"].setContentsMargins(5, 10, 5, 5)
self.layouts["model_tools_layout"].setSpacing(5)
# 模型工具按钮网格
self.layouts["tools_grid"] = QtWidgets.QGridLayout()
self.layouts["tools_grid"].setContentsMargins(0, 0, 0, 0)
self.layouts["tools_grid"].setSpacing(5)
self.layouts["tools_grid"].addWidget(self.buttons["standardize_names"], 0, 0)
self.layouts["tools_grid"].addWidget(self.buttons["auto_group"], 0, 1)
self.layouts["tools_grid"].addWidget(self.buttons["generate_accessories"], 1, 0)
self.layouts["tools_grid"].addWidget(self.buttons["fix_seams"], 1, 1)
self.layouts["tools_grid"].addWidget(self.buttons["fix_vertex_order"], 2, 0, 1, 2)
self.layouts["model_tools_layout"].addLayout(self.layouts["tools_grid"])
# 添加组到右侧面板
self.layouts["right_layout"].addWidget(self.controls["model_properties_group"])
self.layouts["right_layout"].addWidget(self.controls["model_tools_group"])
# 底部工具面板
self.layouts["bottom_panel"] = QtWidgets.QHBoxLayout()
self.layouts["bottom_panel"].setContentsMargins(2, 2, 2, 2)
self.layouts["bottom_panel"].setSpacing(5)
# 导入组布局
self.layouts["import_layout"] = QtWidgets.QVBoxLayout(self.controls["import_group"])
self.layouts["import_layout"].setContentsMargins(5, 10, 5, 5)
self.layouts["import_layout"].setSpacing(5)
self.layouts["import_layout"].addWidget(self.buttons["import_model"])
self.layouts["import_layout"].addWidget(self.buttons["import_fbx"])
self.layouts["import_layout"].addWidget(self.buttons["import_obj"])
# 导出组布局
self.layouts["export_layout"] = QtWidgets.QVBoxLayout(self.controls["export_group"])
self.layouts["export_layout"].setContentsMargins(5, 10, 5, 5)
self.layouts["export_layout"].setSpacing(5)
self.layouts["export_layout"].addWidget(self.buttons["export_model"])
self.layouts["export_layout"].addWidget(self.buttons["export_fbx"])
self.layouts["export_layout"].addWidget(self.buttons["export_obj"])
# 工具组布局
self.layouts["tools_layout"] = QtWidgets.QVBoxLayout(self.controls["tools_group"])
self.layouts["tools_layout"].setContentsMargins(5, 10, 5, 5)
self.layouts["tools_layout"].setSpacing(5)
self.layouts["tools_layout"].addWidget(self.buttons["check_model"])
self.layouts["tools_layout"].addWidget(self.buttons["optimize_model"])
self.layouts["tools_layout"].addWidget(self.buttons["clean_model"])
self.layouts["tools_layout"].addWidget(self.buttons["uv_tools"])
# 添加组到底部面板
self.layouts["bottom_panel"].addWidget(self.controls["import_group"])
self.layouts["bottom_panel"].addWidget(self.controls["export_group"])
self.layouts["bottom_panel"].addWidget(self.controls["tools_group"])
# 添加底部面板到主布局
self.layouts["main_layout"].addLayout(self.layouts["bottom_panel"])
# 将左右面板添加到主分割器
self.splitters["main_splitter"].addWidget(self.controls["left_panel"])
self.splitters["main_splitter"].addWidget(self.controls["right_panel"])
# 设置分割器初始大小和伸缩因子
self.splitters["main_splitter"].setSizes([500, 500])
# 设置分割器的伸缩因子,确保左右栏能够自动调整宽度
for i in range(self.splitters["main_splitter"].count()):
self.splitters["main_splitter"].setStretchFactor(i, 1)
# 添加底部功能按钮区域到主布局
self.layouts["main_layout"].addWidget(self.controls["bottom_area"])
#======================================= CONNECTION =====================================
def create_connections(self):
@@ -427,55 +409,51 @@ class GeometryUI(ui_utils.BaseUI):
# 导入几何工具函数
from scripts.utils import utils_geometry
# 左侧面板连接
# LOD列表连接
self.controls["lod_list"].itemClicked.connect(utils_geometry.lod_selected)
self.controls["lod_list"].itemSelectionChanged.connect(utils_geometry.update_lod_selection)
# 连接LOD标签页的加载按钮
lod_names = [f"LOD{i}" for i in range(8)]
body_parts = [
"头部", "牙齿", "牙龈", "左眼", "右眼", "红脸", "眉毛", "眉毛", "躯体"
]
# LOD操作按钮连接
self.buttons["add_lod"].clicked.connect(utils_geometry.add_lod)
self.buttons["remove_lod"].clicked.connect(utils_geometry.remove_lod)
self.buttons["duplicate_lod"].clicked.connect(utils_geometry.duplicate_lod)
# 根据LOD级别限制连接的身体部位
for lod_name in lod_names:
if lod_name in ["LOD0", "LOD1"]:
parts_to_connect = body_parts
elif lod_name in ["LOD2", "LOD3"]:
parts_to_connect = body_parts[:8]
elif lod_name in ["LOD4", "LOD5"]:
parts_to_connect = body_parts[:5]
else: # LOD6, LOD7
parts_to_connect = body_parts[:4]
# 连接每个身体部位的加载按钮
for part in parts_to_connect:
# 创建一个闭包来保存当前的lod_name和part值
def create_load_callback(lod, part):
return lambda: utils_geometry.load_model_for_lod(lod, part)
# 连接加载按钮
self.buttons[f"{lod_name}_{part}_load"].clicked.connect(
create_load_callback(lod_name, part)
)
# 模型列表连接
self.controls["model_list"].itemClicked.connect(utils_geometry.model_selected)
self.controls["model_list"].itemSelectionChanged.connect(utils_geometry.update_model_selection)
# 连接垃圾桶按钮
self.buttons["delete"].clicked.connect(utils_geometry.delete)
# 模型操作按钮连接
self.buttons["add_model"].clicked.connect(utils_geometry.add_model)
self.buttons["remove_model"].clicked.connect(utils_geometry.remove_model)
self.buttons["duplicate_model"].clicked.connect(utils_geometry.duplicate_model)
# 连接底部功能按钮
# 自动化模型按钮
self.buttons["auto_model"].clicked.connect(utils_geometry.auto_model)
# 右侧面板连接
# 模型属性连接
self.controls["model_name_input"].textChanged.connect(utils_geometry.update_model_name)
self.controls["model_type_combo"].currentIndexChanged.connect(utils_geometry.update_model_type)
self.controls["model_visible_check"].stateChanged.connect(utils_geometry.toggle_model_visibility)
# 属性按钮连接
self.buttons["apply_properties"].clicked.connect(utils_geometry.apply_properties)
self.buttons["reset_properties"].clicked.connect(utils_geometry.reset_properties)
# 模型工具按钮连接
# 标准化名称按钮
self.buttons["standardize_names"].clicked.connect(utils_geometry.standardize_names)
# 自动分组按钮
self.buttons["auto_group"].clicked.connect(utils_geometry.auto_group)
self.buttons["generate_accessories"].clicked.connect(utils_geometry.generate_accessories)
# 模型工具按钮
self.buttons["modify_topology"].clicked.connect(utils_geometry.modify_topology)
self.buttons["fix_seams"].clicked.connect(utils_geometry.fix_seams)
self.buttons["generate_face_components"].clicked.connect(utils_geometry.generate_face_components)
self.buttons["fix_vertex_order"].clicked.connect(utils_geometry.fix_vertex_order)
# 底部工具面板连接
# 导入按钮连接
self.buttons["import_model"].clicked.connect(utils_geometry.import_model)
self.buttons["import_fbx"].clicked.connect(utils_geometry.import_fbx)
self.buttons["import_obj"].clicked.connect(utils_geometry.import_obj)
# 导出按钮连接
self.buttons["export_model"].clicked.connect(utils_geometry.export_model)
self.buttons["export_fbx"].clicked.connect(utils_geometry.export_fbx)
self.buttons["export_obj"].clicked.connect(utils_geometry.export_obj)
# 工具按钮连接
self.buttons["check_model"].clicked.connect(utils_geometry.check_model)
self.buttons["optimize_model"].clicked.connect(utils_geometry.optimize_model)
self.buttons["clean_model"].clicked.connect(utils_geometry.clean_model)
self.buttons["uv_tools"].clicked.connect(utils_geometry.uv_tools)
self.buttons["generate_uvs"].clicked.connect(utils_geometry.generate_uvs)

View File

@@ -358,6 +358,189 @@ def uv_tools():
# 这里实现UV工具的功能
return True
#========================================== LOD相关功能 ========================================
def load_model_for_lod(lod_name, part_name):
"""
为指定LOD的身体部位加载模型
参数:
lod_name: LOD名称"LOD0"
part_name: 身体部位名称,如"头部"
"""
print(f"{lod_name}{part_name}加载模型")
try:
# 打开文件选择对话框
file_path = cmds.fileDialog2(
fileFilter="Maya Files (*.ma *.mb);;OBJ Files (*.obj);;FBX Files (*.fbx);;All Files (*.*)",
dialogStyle=2,
fileMode=1,
caption=f"选择{lod_name}{part_name}模型"
)
if file_path and len(file_path) > 0:
# 根据文件类型导入模型
file_ext = os.path.splitext(file_path[0])[1].lower()
if file_ext in [".ma", ".mb"]:
# 导入Maya文件
cmds.file(file_path[0], i=True, type="mayaAscii" if file_ext == ".ma" else "mayaBinary",
ignoreVersion=True, mergeNamespacesOnClash=False, namespace=f"{lod_name}_{part_name}")
elif file_ext == ".obj":
# 导入OBJ文件
cmds.file(file_path[0], i=True, type="OBJ", ignoreVersion=True,
options="mo=1", namespace=f"{lod_name}_{part_name}")
elif file_ext == ".fbx":
# 导入FBX文件
mel.eval(f'FBXImport -file "{file_path[0]}";')
# 重命名导入的模型
imported_nodes = cmds.ls(sl=True)
if imported_nodes:
for node in imported_nodes:
new_name = f"{lod_name}_{part_name}_{os.path.basename(node)}"
cmds.rename(node, new_name)
print(f"成功为{lod_name}{part_name}加载模型: {file_path[0]}")
return True
except Exception as e:
print(f"加载模型时出错: {e}")
return False
def delete():
"""
删除当前选中的LOD
"""
print("删除LOD")
try:
# 获取当前选中的LOD标签页
tab_widget = cmds.getParent("geometryTabWidget")
if tab_widget:
current_index = cmds.tabLayout(tab_widget, q=True, selectTabIndex=True) - 1
lod_name = f"LOD{current_index}"
# 确认删除
result = cmds.confirmDialog(
title=LANG.get("confirm_delete", "确认删除"),
message=LANG.get("delete_lod_confirm", f"确定要删除{lod_name}吗?"),
button=[LANG.get("yes", ""), LANG.get("no", "")],
defaultButton=LANG.get("no", ""),
cancelButton=LANG.get("no", ""),
dismissString=LANG.get("no", "")
)
if result == LANG.get("yes", ""):
# 删除与该LOD相关的所有模型
nodes_to_delete = cmds.ls(f"{lod_name}_*")
if nodes_to_delete:
cmds.delete(nodes_to_delete)
print(f"{lod_name}已删除")
return True
except Exception as e:
print(f"删除LOD时出错: {e}")
return False
#========================================== 底部功能按钮 ========================================
def auto_model():
"""
自动化模型功能
自动处理模型的各种设置
"""
print("自动化模型")
try:
# 获取当前选中的模型
selected_models = cmds.ls(selection=True, type="transform")
if not selected_models:
cmds.warning(LANG.get("no_model_selected", "未选中模型"))
return False
# 执行标准化命名
standardize_names()
# 执行自动分组
auto_group()
# 执行优化模型
optimize_model()
print("自动化模型完成")
return True
except Exception as e:
print(f"自动化模型时出错: {e}")
return False
def modify_topology():
"""
修改模型拓扑
"""
print("修改模型拓扑")
try:
# 获取当前选中的模型
selected_models = cmds.ls(selection=True, type="transform")
if not selected_models:
cmds.warning(LANG.get("no_model_selected", "未选中模型"))
return False
# 切换到多边形编辑模式
cmds.selectMode(component=True)
cmds.selectType(polymesh=True)
print("进入拓扑编辑模式")
return True
except Exception as e:
print(f"修改模型拓扑时出错: {e}")
return False
def generate_face_components():
"""
生成面部配件
如眉毛、睡毛、泪腺等
"""
print("生成面部配件")
try:
# 获取当前选中的模型
selected_models = cmds.ls(selection=True, type="transform")
if not selected_models:
cmds.warning(LANG.get("no_model_selected", "未选中模型"))
return False
# 生成眉毛
# 这里只是示例代码,实际实现需要更复杂的逻辑
eyebrow_curve = cmds.curve(d=3, p=[(0,0,0), (0.5,0.1,0), (1,0,0)])
cmds.rename(eyebrow_curve, "eyebrow_curve")
# 生成睡毛
eyelash_curve = cmds.curve(d=3, p=[(0,0,0), (0.5,-0.1,0), (1,0,0)])
cmds.rename(eyelash_curve, "eyelash_curve")
print("面部配件生成完成")
return True
except Exception as e:
print(f"生成面部配件时出错: {e}")
return False
def generate_uvs():
"""
生成模型UV
"""
print("生成模型UV")
try:
# 获取当前选中的模型
selected_models = cmds.ls(selection=True, type="transform")
if not selected_models:
cmds.warning(LANG.get("no_model_selected", "未选中模型"))
return False
# 为每个选中的模型生成UV
for model in selected_models:
# 使用Maya的自动UV展开功能
cmds.polyAutoProjection(model, constructionHistory=True, layout=2, optimize=1, percentageSpace=0.2)
print("UV生成完成")
return True
except Exception as e:
print(f"生成UV时出错: {e}")
return False
# 保留原来的函数作为兼容性考虑
def geometry_temp_utils_function():
"""