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)