Update
This commit is contained in:
@@ -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)
|
@@ -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():
|
||||
"""
|
||||
|
Reference in New Issue
Block a user