This commit is contained in:
2025-05-08 23:57:22 +08:00
parent 24acc2a6f1
commit 7094a5886a
18 changed files with 442 additions and 583 deletions

View File

@@ -16,8 +16,8 @@ Geometry UI Module for Plugin
- 修复点序
"""
#========================================= IMPORT =========================================
from Qt import QtWidgets, QtCore, QtGui
from Qt.QtCompat import wrapInstance
from scripts.ui.Qt import QtWidgets, QtCore, QtGui
from scripts.ui.Qt.QtCompat import wrapInstance
from maya import OpenMayaUI as omui
import maya.cmds as cmds
import maya.mel as mel
@@ -56,22 +56,16 @@ TOOL_WIDTH = config.TOOL_WIDTH
TOOL_HEIGHT = config.TOOL_HEIGHT
#========================================= LOCATION =======================================
from scripts.ui import localization
LANG = localization.LANG
get_text = localization.get_text
TEXT = localization.TEXT
class GeometryUI(ui_utils.BaseUI):
"""
几何模型UI类 - 负责显示几何模型编辑界面和基础操作
继承自BaseUI类实现几何模型相关的UI功能
"""
#========================================== INIT ========================================
def __init__(self):
"""
初始化几何模型UI
创建主控件和布局,并连接信号和槽
"""
super(GeometryUI, self).__init__()
# 只继承BaseUI不自定义单例相关代码
def __init__(self, parent=None):
super().__init__(parent)
# 创建主控件
self.main_widget = QtWidgets.QWidget()
self.main_widget.setObjectName("geometryMainWidget")
@@ -80,6 +74,9 @@ class GeometryUI(ui_utils.BaseUI):
self.create_widgets()
self.create_layouts()
self.create_connections()
# 更新UI文本
self.update_language()
#========================================= WIDGET =======================================
def create_widgets(self):
@@ -88,7 +85,7 @@ class GeometryUI(ui_utils.BaseUI):
包括按钮、标签、列表等
"""
# 标题标签 - 使用HTML格式化标题
title_text = f"<h4 style='margin:0;padding:5px;'>{get_text('geometry_title', '几何模型')}</h4>"
title_text = f"<h4 style='margin:0;padding:5px;'>{TEXT('geometry_title', '几何模型')}</h4>"
self.controls["title_label"] = QtWidgets.QLabel(title_text)
self.controls["title_label"].setObjectName("geometryTitleLabel")
self.controls["title_label"].setAlignment(QtCore.Qt.AlignCenter)
@@ -107,115 +104,6 @@ class GeometryUI(ui_utils.BaseUI):
# 创建底部功能按钮区域
self.create_bottom_buttons()
# 模型列表
self.controls["model_list"] = QtWidgets.QListWidget()
self.controls["model_list"].setObjectName("modelList")
# 模型操作按钮
self.buttons["add_model"] = QtWidgets.QPushButton(get_text("add_model", "添加模型"))
self.buttons["add_model"].setObjectName("addModelButton")
self.buttons["remove_model"] = QtWidgets.QPushButton(get_text("remove_model", "移除模型"))
self.buttons["remove_model"].setObjectName("removeModelButton")
self.buttons["duplicate_model"] = QtWidgets.QPushButton(get_text("duplicate_model", "复制模型"))
self.buttons["duplicate_model"].setObjectName("duplicateModelButton")
# 右侧面板控件 - 模型属性
self.controls["model_properties_group"] = QtWidgets.QGroupBox(get_text("model_properties", "模型属性"))
self.controls["model_properties_group"].setObjectName("modelPropertiesGroup")
# 模型名称标签和输入框
self.controls["model_name_label"] = QtWidgets.QLabel(get_text("name", "名称:"))
self.controls["model_name_label"].setObjectName("modelNameLabel")
self.controls["model_name_input"] = QtWidgets.QLineEdit()
self.controls["model_name_input"].setObjectName("modelNameInput")
self.controls["model_name_input"].setPlaceholderText(get_text("enter_model_name", "输入模型名称"))
# 模型类型标签和下拉框
self.controls["model_type_label"] = QtWidgets.QLabel(get_text("type", "类型:"))
self.controls["model_type_label"].setObjectName("modelTypeLabel")
self.controls["model_type_combo"] = QtWidgets.QComboBox()
self.controls["model_type_combo"].setObjectName("modelTypeCombo")
self.controls["model_type_combo"].addItems(["Base", "Head", "Body", "Accessory", "Other"])
# 模型可见性复选框
self.controls["model_visible_check"] = QtWidgets.QCheckBox(get_text("visible", "可见"))
self.controls["model_visible_check"].setObjectName("modelVisibleCheck")
self.controls["model_visible_check"].setChecked(True)
# 模型属性按钮
self.buttons["apply_properties"] = QtWidgets.QPushButton(get_text("apply", "应用"))
self.buttons["apply_properties"].setObjectName("applyPropertiesButton")
self.buttons["reset_properties"] = QtWidgets.QPushButton(get_text("reset", "重置"))
self.buttons["reset_properties"].setObjectName("resetPropertiesButton")
# 右侧面板控件 - 模型工具
self.controls["model_tools_group"] = QtWidgets.QGroupBox(get_text("model_tools", "模型工具"))
self.controls["model_tools_group"].setObjectName("modelToolsGroup")
# 模型工具按钮
self.buttons["standardize_names"] = QtWidgets.QPushButton(get_text("standardize_names", "标准化命名"))
self.buttons["standardize_names"].setObjectName("standardizeNamesButton")
self.buttons["auto_group"] = QtWidgets.QPushButton(get_text("auto_group", "自动分组"))
self.buttons["auto_group"].setObjectName("autoGroupButton")
self.buttons["generate_accessories"] = QtWidgets.QPushButton(get_text("generate_accessories", "生成配件"))
self.buttons["generate_accessories"].setObjectName("generateAccessoriesButton")
self.buttons["fix_seams"] = QtWidgets.QPushButton(get_text("fix_seams", "修复接缝"))
self.buttons["fix_seams"].setObjectName("fixSeamsButton")
self.buttons["fix_vertex_order"] = QtWidgets.QPushButton(get_text("fix_vertex_order", "修复点序"))
self.buttons["fix_vertex_order"].setObjectName("fixVertexOrderButton")
# 底部工具面板
# 导入部分
self.controls["import_group"] = QtWidgets.QGroupBox(get_text("import", "导入"))
self.controls["import_group"].setObjectName("importGroup")
self.buttons["import_model"] = QtWidgets.QPushButton(get_text("import_model", "导入模型"))
self.buttons["import_model"].setObjectName("importModelButton")
self.buttons["import_fbx"] = QtWidgets.QPushButton(get_text("import_fbx", "导入FBX"))
self.buttons["import_fbx"].setObjectName("importFbxButton")
self.buttons["import_obj"] = QtWidgets.QPushButton(get_text("import_obj", "导入OBJ"))
self.buttons["import_obj"].setObjectName("importObjButton")
# 导出部分
self.controls["export_group"] = QtWidgets.QGroupBox(get_text("export", "导出"))
self.controls["export_group"].setObjectName("exportGroup")
self.buttons["export_model"] = QtWidgets.QPushButton(get_text("export_model", "导出模型"))
self.buttons["export_model"].setObjectName("exportModelButton")
self.buttons["export_fbx"] = QtWidgets.QPushButton(get_text("export_fbx", "导出 FBX"))
self.buttons["export_fbx"].setObjectName("exportFbxButton")
self.buttons["export_obj"] = QtWidgets.QPushButton(get_text("export_obj", "导出 OBJ"))
self.buttons["export_obj"].setObjectName("exportObjButton")
# 工具部分
self.controls["tools_group"] = QtWidgets.QGroupBox(get_text("tools", "工具"))
self.controls["tools_group"].setObjectName("toolsGroup")
self.buttons["check_model"] = QtWidgets.QPushButton(get_text("check_model", "检查模型"))
self.buttons["check_model"].setObjectName("checkModelButton")
self.buttons["optimize_model"] = QtWidgets.QPushButton(get_text("optimize_model", "优化模型"))
self.buttons["optimize_model"].setObjectName("optimizeModelButton")
self.buttons["clean_model"] = QtWidgets.QPushButton(get_text("clean_model", "清理模型"))
self.buttons["clean_model"].setObjectName("cleanModelButton")
self.buttons["uv_tools"] = QtWidgets.QPushButton(get_text("uv_tools", "UV工具"))
self.buttons["uv_tools"].setObjectName("uvToolsButton")
def create_lod_tabs(self):
"""
@@ -274,15 +162,15 @@ class GeometryUI(ui_utils.BaseUI):
# 输入框
line_edit = QtWidgets.QLineEdit()
line_edit.setPlaceholderText(get_text("enter_model_name", "输入模型名称"))
line_edit.setPlaceholderText(TEXT("enter_model_name", "输入模型名称"))
line_edit.setObjectName(f"{lod_name}_{part}_input")
# 创建加载按钮(统一插件风格)
load_button = QtWidgets.QPushButton(get_text(" load ", " 加 载 "))
load_button.setObjectName("{TOOL_NAME}LoadButton")
# 创建加载按钮(统一风格)
load_button = QtWidgets.QPushButton(TEXT("load", " 加 载 "))
load_button.setObjectName("LoadButton")
load_button.setIcon(QtGui.QIcon(os.path.join(ICONS_PATH, "loading.png")))
load_button.setIconSize(QtCore.QSize(16, 16))
load_button.setToolTip(get_text("load_model", "加载模型"))
load_button.setToolTip(TEXT("load_model", "加载模型"))
load_button.setFixedSize(105, 24) # 更紧凑,和输入框高度完全一致
load_button.setStyleSheet("""
QPushButton {
@@ -308,24 +196,57 @@ class GeometryUI(ui_utils.BaseUI):
# 添加弹性空间
tab_layout.addStretch(1)
# === 添加LOD专属底部三大按钮 ===
lod_buttons_layout = QtWidgets.QHBoxLayout()
lod_buttons_layout.setContentsMargins(0, 0, 0, 0)
lod_buttons_layout.setSpacing(10)
btn_auto_load = QtWidgets.QPushButton(TEXT("auto_load_meshes", "自动加载模型"))
btn_auto_load.setIcon(ui_utils.load_icon("load_meshes.png"))
btn_auto_load.setIconSize(QtCore.QSize(20, 20))
btn_auto_load.setObjectName(f"{lod_name}_autoLoadMeshesButton")
btn_auto_load.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
btn_standardized = QtWidgets.QPushButton(TEXT("standardized_naming", "标准化命名"))
btn_standardized.setIcon(ui_utils.load_icon("standardized_naming.png"))
btn_standardized.setIconSize(QtCore.QSize(20, 20))
btn_standardized.setObjectName(f"{lod_name}_standardizedNamingButton")
btn_standardized.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
btn_auto_group = QtWidgets.QPushButton(TEXT("automatic_grouping", "自动分组"))
btn_auto_group.setIcon(ui_utils.load_icon("automatic_grouping.png"))
btn_auto_group.setIconSize(QtCore.QSize(20, 20))
btn_auto_group.setObjectName(f"{lod_name}_automaticGroupingButton")
btn_auto_group.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
lod_buttons_layout.addWidget(btn_auto_load, 1)
lod_buttons_layout.addWidget(btn_standardized, 1)
lod_buttons_layout.addWidget(btn_auto_group, 1)
tab_layout.addLayout(lod_buttons_layout)
# 保存引用(如需后续操作)
self.buttons[f"{lod_name}_auto_load_meshes"] = btn_auto_load
self.buttons[f"{lod_name}_standardized_naming"] = btn_standardized
self.buttons[f"{lod_name}_automatic_grouping"] = btn_auto_group
# 将标签页添加到标签页控件
self.controls["tab_widget"].addTab(tab, lod_name)
# 创建清理按钮
self.buttons["clean"] = QtWidgets.QPushButton(get_text("clean", " 清 理 "))
self.buttons["clean"].setObjectName("clearButton")
self.buttons["clean"].setIcon(ui_utils.load_icon("delete.png"))
self.buttons["clean"].setIconSize(QtCore.QSize(16, 16))
self.buttons["clean"].setFixedSize(150, 28)
self.buttons["clean"].setToolTip(get_text("clear_all_models", "清理所有模型"))
self.buttons["clean"].setStyleSheet("""
self.buttons["clear"] = QtWidgets.QPushButton(TEXT("clear", " 清 理 "))
self.buttons["clear"].setObjectName("clearButton")
self.buttons["clear"].setIcon(ui_utils.load_icon("delete.png"))
self.buttons["clear"].setIconSize(QtCore.QSize(16, 16))
self.buttons["clear"].setFixedSize(150, 28)
self.buttons["clear"].setToolTip(TEXT("clear_all_models", "清理所有模型"))
self.buttons["clear"].setStyleSheet("""
QPushButton {
padding: 2px 2px;
margin: 0px 50px 0px 0px; /* 上右下左的边距,增加上边距避免与标签栏重叠 */
}
""")
self.buttons["clean"].setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
self.buttons["clear"].setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
def create_bottom_buttons(self):
"""
@@ -344,7 +265,7 @@ class GeometryUI(ui_utils.BaseUI):
bottom_layout.setSpacing(5)
# 创建模型工具区域
model_tools_group = QtWidgets.QGroupBox(get_text("model_tools", "模型工具"))
model_tools_group = QtWidgets.QGroupBox(TEXT("model_tools", "模型工具"))
model_tools_group.setObjectName("modelToolsGroup")
# 创建模型工具布局
@@ -365,7 +286,7 @@ class GeometryUI(ui_utils.BaseUI):
topology_container_layout = QtWidgets.QHBoxLayout(topology_container)
topology_container_layout.setContentsMargins(5, 5, 5, 5)
topology_label = QtWidgets.QLabel(get_text("topology_structure", "拓扑结构") + ":")
topology_label = QtWidgets.QLabel(TEXT("topology_structure", "拓扑结构") + ":")
self.controls["topology_combo"] = QtWidgets.QComboBox()
self.controls["topology_combo"].setObjectName("topologyCombo")
self.controls["topology_combo"].addItem("MetaHuman")
@@ -379,10 +300,10 @@ class GeometryUI(ui_utils.BaseUI):
lod_container_layout = QtWidgets.QHBoxLayout(lod_container)
lod_container_layout.setContentsMargins(5, 5, 5, 5)
lod_label = QtWidgets.QLabel(get_text("select_lod", "选择LOD") + ":")
lod_label = QtWidgets.QLabel(TEXT("select_lod", "选择LOD") + ":")
self.controls["lod_combo"] = QtWidgets.QComboBox()
self.controls["lod_combo"].setObjectName("lodCombo")
self.controls["lod_combo"].addItem(get_text("all", "全部"))
self.controls["lod_combo"].addItem(TEXT("all", "全部"))
for i in range(8): # LOD0~LOD7
self.controls["lod_combo"].addItem(f"LOD{i}")
@@ -395,7 +316,7 @@ class GeometryUI(ui_utils.BaseUI):
button_container_layout = QtWidgets.QHBoxLayout(button_container)
button_container_layout.setContentsMargins(5, 5, 5, 5)
self.buttons["create_lod"] = QtWidgets.QPushButton(get_text("create_lod", "创建LOD"))
self.buttons["create_lod"] = QtWidgets.QPushButton(TEXT("create_lod", "创建LOD"))
self.buttons["create_lod"].setObjectName("createLodButton")
self.buttons["create_lod"].setIcon(ui_utils.load_icon("create_lod.png"))
self.buttons["create_lod"].setMinimumHeight(30)
@@ -413,31 +334,26 @@ class GeometryUI(ui_utils.BaseUI):
# 将水平布局添加到模型工具布局
model_tools_layout.addLayout(self.layouts["top_row_layout"], 0, 0, 1, 5)
# 创建模型工具按钮
# 设置按钮的尺寸策略,使其均等撑满一行
# 保留原有按钮行布局
size_policy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
# 创建每行按钮的布局
self.layouts["buttons_row1_layout"] = QtWidgets.QHBoxLayout()
self.layouts["buttons_row1_layout"].setContentsMargins(0, 0, 0, 0)
self.layouts["buttons_row1_layout"].setSpacing(10)
self.layouts["buttons_row2_layout"] = QtWidgets.QHBoxLayout()
self.layouts["buttons_row2_layout"].setContentsMargins(0, 0, 0, 0)
self.layouts["buttons_row2_layout"].setSpacing(10)
self.layouts["buttons_row3_layout"] = QtWidgets.QHBoxLayout()
self.layouts["buttons_row3_layout"].setContentsMargins(0, 0, 0, 0)
self.layouts["buttons_row3_layout"].setSpacing(10)
# 第一行按钮
self.buttons["separate_model"] = QtWidgets.QPushButton(get_text("separate_model", "模型分离"))
self.buttons["separate_model"] = QtWidgets.QPushButton(TEXT("separate_model", "模型分离"))
self.buttons["separate_model"].setObjectName("separateModelButton")
self.buttons["separate_model"].setIcon(ui_utils.load_icon("polySplitVertex.png"))
self.buttons["separate_model"].setMinimumHeight(30)
self.buttons["separate_model"].setSizePolicy(size_policy)
self.buttons["generate_face_components"] = QtWidgets.QPushButton(get_text("generate_face_components", "生成面部配件"))
self.buttons["generate_face_components"] = QtWidgets.QPushButton(TEXT("generate_face_components", "生成面部配件"))
self.buttons["generate_face_components"].setObjectName("generateFaceComponentsButton")
self.buttons["generate_face_components"].setIcon(ui_utils.load_icon("meshes.png"))
self.buttons["generate_face_components"].setMinimumHeight(30)
@@ -448,13 +364,13 @@ class GeometryUI(ui_utils.BaseUI):
self.layouts["buttons_row1_layout"].addWidget(self.buttons["generate_face_components"])
# 第二行按钮
self.buttons["fix_normals"] = QtWidgets.QPushButton(get_text("fix_normals", "修复法线"))
self.buttons["fix_normals"] = QtWidgets.QPushButton(TEXT("fix_normals", "修复法线"))
self.buttons["fix_normals"].setObjectName("fixNormalsButton")
self.buttons["fix_normals"].setIcon(ui_utils.load_icon("repair_normals.png"))
self.buttons["fix_normals"].setMinimumHeight(30)
self.buttons["fix_normals"].setSizePolicy(size_policy)
self.buttons["fix_vertex_order"] = QtWidgets.QPushButton(get_text("fix_vertex_order", "修复点序"))
self.buttons["fix_vertex_order"] = QtWidgets.QPushButton(TEXT("fix_vertex_order", "修复点序"))
self.buttons["fix_vertex_order"].setObjectName("fixVertexOrderButton")
self.buttons["fix_vertex_order"].setIcon(ui_utils.load_icon("repair_vertex_order.png"))
self.buttons["fix_vertex_order"].setMinimumHeight(30)
@@ -465,13 +381,13 @@ class GeometryUI(ui_utils.BaseUI):
self.layouts["buttons_row2_layout"].addWidget(self.buttons["fix_vertex_order"])
# 第三行按钮
self.buttons["fix_seams"] = QtWidgets.QPushButton(get_text("fix_seams", "修复接缝"))
self.buttons["fix_seams"] = QtWidgets.QPushButton(TEXT("fix_seams", "修复接缝"))
self.buttons["fix_seams"].setObjectName("fixSeamsButton")
self.buttons["fix_seams"].setIcon(ui_utils.load_icon("polyChipOff.png"))
self.buttons["fix_seams"].setMinimumHeight(30)
self.buttons["fix_seams"].setSizePolicy(size_policy)
self.buttons["optimize_scene"] = QtWidgets.QPushButton(get_text("optimize_scene", "优化场景"))
self.buttons["optimize_scene"] = QtWidgets.QPushButton(TEXT("optimize_scene", "优化场景"))
self.buttons["optimize_scene"].setObjectName("optimizeSceneButton")
self.buttons["optimize_scene"].setIcon(ui_utils.load_icon("singlePerspLayout.png"))
self.buttons["optimize_scene"].setMinimumHeight(30)
@@ -505,7 +421,7 @@ class GeometryUI(ui_utils.BaseUI):
# 将清理按钮直接添加到标签页控件的右上角
# 设置标签页控件的角落部件
self.controls["tab_widget"].setCornerWidget(self.buttons["clean"], QtCore.Qt.TopRightCorner)
self.controls["tab_widget"].setCornerWidget(self.buttons["clear"], QtCore.Qt.TopRightCorner)
# 添加标签页控件到主布局
self.layouts["main_layout"].addWidget(self.controls["tab_widget"])
@@ -563,7 +479,7 @@ class GeometryUI(ui_utils.BaseUI):
)
# 连接清理按钮
self.buttons["clean"].clicked.connect(utils_geometry.clean)
self.buttons["clear"].clicked.connect(utils_geometry.clean)
# 连接拓扑结构下拉框
self.controls["topology_combo"].currentIndexChanged.connect(utils_geometry.update_topology)