This commit is contained in:
2025-05-05 18:15:02 +08:00
parent 01c0ec760f
commit 46d93efb3c
11 changed files with 1728 additions and 1943 deletions

View File

@@ -11,159 +11,232 @@ Geometry UI Module for Plugin
- 自动加载模型
- 标准化命名
- 自动分组
- 生成面部配件(毛,舌头,泪腺 等)
- 生成面部配件(毛,舌头,泪腺 等)
- 修复接缝(修复法线)
- 修复点序
"""
#===================================== IMPORT MODULES =====================================
#========================================= IMPORT =========================================
from Qt import QtWidgets, QtCore, QtGui
from Qt.QtCompat import wrapInstance
from maya import OpenMayaUI as omui
import maya.cmds as cmds
import maya.mel as mel
import maya.utils as utils
import webbrowser
import subprocess
import importlib
import traceback
import locale
import sys
import os
#===================================== IMPORT FUNCTIONS ===================================
from scripts.utils import utils_geometry as utils_geometry
from scripts.ui import ui_utils
from scripts.utils import utils_geometry
#========================================== CONFIG ========================================
import config
TOOL_NAME = config.TOOL_NAME
TOOL_VERSION = config.TOOL_VERSION
TOOL_AUTHOR = config.TOOL_AUTHOR
TOOL_YEAR = config.TOOL_YEAR
TOOL_MOD_FILENAME = config.TOOL_MOD_FILENAME
TOOL_LANG = config.TOOL_LANG
TOOL_WSCL_NAME = config.TOOL_WSCL_NAME
TOOL_HELP_URL = config.TOOL_HELP_URL
TOOL_PATH = config.TOOL_PATH
SCRIPTS_PATH = config.SCRIPTS_PATH
TOOL_MAIN_SCRIPT = config.TOOL_MAIN_SCRIPT
UI_PATH = config.UI_PATH
STYLE_FILE = config.STYLE_FILE
ICONS_PATH = config.ICONS_PATH
TOOL_ICON = config.TOOL_ICON
ASSETS_PATH = config.ASSETS_PATH
DNA_FILE_PATH = config.DNA_FILE_PATH
DNA_IMG_PATH = config.DNA_IMG_PATH
TOOL_COMMAND_ICON = config.TOOL_COMMAND_ICON
#========================================= LOCATION =======================================
from scripts.ui import localization
LANG = localization.LANG
#========================================== WIDGETS ==========================================
# 全局变量存储UI控件
model_tree = None
lod_combo = None
model_buttons = {}
model_info_panel = None
class GeometryUI(ui_utils.BaseUI):
"""
几何模型UI类 - 负责显示几何模型编辑界面和基础操作
继承自BaseUI类实现几何模型相关的UI功能
"""
#========================================== INIT ========================================
def __init__(self):
"""
初始化几何模型UI
创建主控件和布局,并连接信号和槽
"""
super(GeometryUI, self).__init__()
# 创建主控件
self.main_widget = QtWidgets.QWidget()
self.main_widget.setObjectName("geometryMainWidget")
# 初始化UI
self.create_widgets()
self.create_layouts()
self.create_connections()
def widgets():
"""
创建几何模型UI控件
"""
global model_tree, lod_combo, model_buttons, model_info_panel
# LOD选择下拉菜单
lod_combo = QtWidgets.QComboBox()
lod_combo.addItems(["LOD0", "LOD1", "LOD2", "LOD3", "LOD4"])
lod_combo.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
lod_combo.setMinimumWidth(100)
# 模型树形视图
model_tree = QtWidgets.QTreeWidget()
model_tree.setHeaderLabels(["模型名称", "顶点数", "面数"])
model_tree.setMinimumHeight(250)
model_tree.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
model_tree.header().setSectionResizeMode(QtWidgets.QHeaderView.Stretch) # 列自动拉伸
# 模型信息面板
model_info_panel = QtWidgets.QTextEdit()
model_info_panel.setReadOnly(True)
model_info_panel.setMinimumHeight(100)
model_info_panel.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
# 功能按钮 - 设置统一的大小策略
for button_name in ["load_model", "create_lod", "auto_load", "standardize_name",
"auto_group", "generate_accessories", "fix_seams", "fix_vertex_order"]:
model_buttons[button_name] = QtWidgets.QPushButton({
"load_model": "加载模型",
"create_lod": "创建LOD",
"auto_load": "自动加载",
"standardize_name": "标准化命名",
"auto_group": "自动分组",
"generate_accessories": "生成面部配件",
"fix_seams": "修复接缝",
"fix_vertex_order": "修复点序"
}[button_name])
model_buttons[button_name].setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
model_buttons[button_name].setMinimumWidth(120)
#========================================= WIDGET =======================================
def create_widgets(self):
"""
创建几何模型UI控件
包括按钮、标签、列表等
"""
# 标题标签
self.controls["title_label"] = QtWidgets.QLabel(LANG.get("geometry_title", "几何模型"))
self.controls["title_label"].setObjectName("geometryTitleLabel")
self.controls["title_label"].setAlignment(QtCore.Qt.AlignCenter)
# 创建主分割器
self.splitters["main_splitter"] = QtWidgets.QSplitter(QtCore.Qt.Horizontal)
self.splitters["main_splitter"].setObjectName("geometryMainSplitter")
# 左侧面板
self.controls["left_panel"] = QtWidgets.QWidget()
self.controls["left_panel"].setObjectName("geometryLeftPanel")
# 右侧面板
self.controls["right_panel"] = QtWidgets.QWidget()
self.controls["right_panel"].setObjectName("geometryRightPanel")
# 左侧面板控件
# 模型列表组
self.controls["model_group"] = QtWidgets.QGroupBox(LANG.get("model_group", "模型列表"))
self.controls["model_group"].setObjectName("modelGroup")
# 模型列表
self.controls["model_list"] = QtWidgets.QListWidget()
self.controls["model_list"].setObjectName("modelList")
# 模型刷新按钮
self.buttons["refresh_models"] = QtWidgets.QPushButton(LANG.get("refresh", "刷新"))
self.buttons["refresh_models"].setObjectName("refreshModelsButton")
# LOD过滤组
self.controls["lod_filter_group"] = QtWidgets.QGroupBox(LANG.get("lod_filter_group", "LOD过滤"))
self.controls["lod_filter_group"].setObjectName("lodFilterGroup")
# LOD选择
self.controls["lod_label"] = QtWidgets.QLabel(LANG.get("lod", "LOD:"))
self.controls["lod_combo"] = QtWidgets.QComboBox()
self.controls["lod_combo"].setObjectName("lodCombo")
# 右侧面板控件
# 模型操作组
self.controls["model_ops_group"] = QtWidgets.QGroupBox(LANG.get("model_operations", "模型操作"))
self.controls["model_ops_group"].setObjectName("modelOpsGroup")
# 模型操作按钮
self.buttons["pick_model"] = QtWidgets.QPushButton(LANG.get("pick_model", "拾取模型"))
self.buttons["load_model"] = QtWidgets.QPushButton(LANG.get("load_model", "加载模型"))
self.buttons["create_lod"] = QtWidgets.QPushButton(LANG.get("create_lod", "创建LOD"))
self.buttons["auto_load"] = QtWidgets.QPushButton(LANG.get("auto_load", "自动加载"))
# 模型工具组
self.controls["model_tools_group"] = QtWidgets.QGroupBox(LANG.get("model_tools", "模型工具"))
self.controls["model_tools_group"].setObjectName("modelToolsGroup")
# 模型工具按钮
self.buttons["standardize_names"] = QtWidgets.QPushButton(LANG.get("standardize_names", "标准化命名"))
self.buttons["auto_group"] = QtWidgets.QPushButton(LANG.get("auto_group", "自动分组"))
self.buttons["generate_accessories"] = QtWidgets.QPushButton(LANG.get("generate_accessories", "生成面部配件"))
self.buttons["fix_seams"] = QtWidgets.QPushButton(LANG.get("fix_seams", "修复接缝"))
self.buttons["fix_vertex_order"] = QtWidgets.QPushButton(LANG.get("fix_vertex_order", "修复点序"))
#========================================== LAYOUTS ==========================================
def layouts(parent_tab=None):
"""
创建几何模型UI布局
Args:
parent_tab: 父容器控件由Main.py传入
"""
# 获取父容器在Main.py中创建的geometry_tab
if not parent_tab:
parent_tab = ui_utils.get_parent_widget("geometry_tab")
if not parent_tab:
print("无法获取父容器,布局创建失败")
return
# 创建主布局
main_layout = parent_tab.layout()
if not main_layout:
main_layout = QtWidgets.QVBoxLayout(parent_tab)
main_layout.setContentsMargins(4, 4, 4, 4)
main_layout.setSpacing(4)
main_layout.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint) # 设置布局约束为默认,允许自适应
# 创建分割控件
splitter = QtWidgets.QSplitter(QtCore.Qt.Vertical)
# 上部区域 - LOD选择和模型树
top_widget = QtWidgets.QWidget()
top_layout = QtWidgets.QVBoxLayout(top_widget)
top_layout.setContentsMargins(0, 0, 0, 0)
# LOD选择区域
lod_layout = QtWidgets.QHBoxLayout()
lod_layout.addWidget(QtWidgets.QLabel("LOD级别:"))
lod_layout.addWidget(lod_combo)
lod_layout.addStretch()
top_layout.addLayout(lod_layout)
# 模型树区域
model_group = QtWidgets.QGroupBox("模型列表")
model_layout = QtWidgets.QVBoxLayout(model_group)
model_layout.addWidget(model_tree)
top_layout.addWidget(model_group)
# 下部区域 - 模型信息
model_info_group = QtWidgets.QGroupBox("模型信息")
model_info_layout = QtWidgets.QVBoxLayout(model_info_group)
model_info_layout.addWidget(model_info_panel)
# 添加到分割控件
splitter.addWidget(top_widget)
splitter.addWidget(model_info_group)
# 按钮区域
button_layout = QtWidgets.QGridLayout()
button_layout.addWidget(model_buttons["load_model"], 0, 0)
button_layout.addWidget(model_buttons["create_lod"], 0, 1)
button_layout.addWidget(model_buttons["auto_load"], 1, 0)
button_layout.addWidget(model_buttons["standardize_name"], 1, 1)
button_layout.addWidget(model_buttons["auto_group"], 2, 0)
button_layout.addWidget(model_buttons["generate_accessories"], 2, 1)
button_layout.addWidget(model_buttons["fix_seams"], 3, 0)
button_layout.addWidget(model_buttons["fix_vertex_order"], 3, 1)
# 添加到主布局
main_layout.addWidget(splitter)
main_layout.addLayout(button_layout)
#========================================= LAYOUT =======================================
def create_layouts(self):
"""
创建几何模型UI布局
组织控件的排列和层次结构
"""
# 主布局
self.layouts["main_layout"] = QtWidgets.QVBoxLayout(self.main_widget)
self.layouts["main_layout"].setContentsMargins(5, 5, 5, 5)
self.layouts["main_layout"].setSpacing(5)
# 添加标题标签
self.layouts["main_layout"].addWidget(self.controls["title_label"])
# 添加主分割器
self.layouts["main_layout"].addWidget(self.splitters["main_splitter"])
# 将左右面板添加到主分割器
self.splitters["main_splitter"].addWidget(self.controls["left_panel"])
self.splitters["main_splitter"].addWidget(self.controls["right_panel"])
# 左侧面板布局
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)
# 模型列表组布局
self.layouts["model_list_layout"] = QtWidgets.QVBoxLayout(self.controls["model_group"])
self.layouts["model_list_layout"].addWidget(self.controls["model_list"])
self.layouts["model_list_layout"].addWidget(self.buttons["refresh_models"])
# LOD过滤组布局
self.layouts["lod_filter_layout"] = QtWidgets.QHBoxLayout(self.controls["lod_filter_group"])
self.layouts["lod_filter_layout"].addWidget(self.controls["lod_label"])
self.layouts["lod_filter_layout"].addWidget(self.controls["lod_combo"])
# 添加组到左侧面板布局
self.layouts["left_layout"].addWidget(self.controls["model_group"])
self.layouts["left_layout"].addWidget(self.controls["lod_filter_group"])
self.layouts["left_layout"].addStretch()
# 右侧面板布局
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_ops_layout"] = QtWidgets.QVBoxLayout(self.controls["model_ops_group"])
self.layouts["model_ops_layout"].addWidget(self.buttons["pick_model"])
self.layouts["model_ops_layout"].addWidget(self.buttons["load_model"])
self.layouts["model_ops_layout"].addWidget(self.buttons["create_lod"])
self.layouts["model_ops_layout"].addWidget(self.buttons["auto_load"])
# 模型工具组布局
self.layouts["model_tools_layout"] = QtWidgets.QVBoxLayout(self.controls["model_tools_group"])
self.layouts["model_tools_layout"].addWidget(self.buttons["standardize_names"])
self.layouts["model_tools_layout"].addWidget(self.buttons["auto_group"])
self.layouts["model_tools_layout"].addWidget(self.buttons["generate_accessories"])
self.layouts["model_tools_layout"].addWidget(self.buttons["fix_seams"])
self.layouts["model_tools_layout"].addWidget(self.buttons["fix_vertex_order"])
# 添加组到右侧面板布局
self.layouts["right_layout"].addWidget(self.controls["model_ops_group"])
self.layouts["right_layout"].addWidget(self.controls["model_tools_group"])
self.layouts["right_layout"].addStretch()
# 创建分割器大小处理器
self.resize_handlers["main_splitter"] = ui_utils.SplitterResizeHandler(
self.main_widget, self.splitters["main_splitter"], is_horizontal=True
)
#========================================== CONNECTIONS ==========================================
def connections():
"""
连接几何模型UI信号和槽
"""
# 连接按钮点击事件到占位函数
model_buttons["load_model"].clicked.connect(lambda: print("加载模型功能待实现"))
model_buttons["create_lod"].clicked.connect(lambda: print("创建LOD功能待实现"))
model_buttons["auto_load"].clicked.connect(lambda: print("自动加载功能待实现"))
model_buttons["standardize_name"].clicked.connect(lambda: print("标准化命名功能待实现"))
model_buttons["auto_group"].clicked.connect(lambda: print("自动分组功能待实现"))
model_buttons["generate_accessories"].clicked.connect(lambda: print("生成面部配件功能待实现"))
model_buttons["fix_seams"].clicked.connect(lambda: print("修复接缝功能待实现"))
model_buttons["fix_vertex_order"].clicked.connect(lambda: print("修复点序功能待实现"))
# 连接LOD选择事件
lod_combo.currentIndexChanged.connect(lambda index: print(f"选择的LOD级别: {lod_combo.currentText()}"))
# 连接模型树选择事件
model_tree.itemSelectionChanged.connect(lambda: print("模型选择已更改"))
#===================================== PLACEHOLDER FUNCTION ===================================
def geometry_temp_function():
return utils_geometry.geometry_temp_utils_function()
#======================================= CONNECTION =====================================
def create_connections(self):
"""
连接信号和槽
设置UI控件的交互行为
"""
# 模型列表按钮连接
self.buttons["refresh_models"].clicked.connect(utils_geometry.geometry_temp_utils_function)
# LOD过滤连接
self.controls["lod_combo"].currentIndexChanged.connect(utils_geometry.geometry_temp_utils_function)
# 模型操作按钮连接
self.buttons["pick_model"].clicked.connect(utils_geometry.geometry_temp_utils_function)
self.buttons["load_model"].clicked.connect(utils_geometry.geometry_temp_utils_function)
self.buttons["create_lod"].clicked.connect(utils_geometry.geometry_temp_utils_function)
self.buttons["auto_load"].clicked.connect(utils_geometry.geometry_temp_utils_function)
# 模型工具按钮连接
self.buttons["standardize_names"].clicked.connect(utils_geometry.geometry_temp_utils_function)
self.buttons["auto_group"].clicked.connect(utils_geometry.geometry_temp_utils_function)
self.buttons["generate_accessories"].clicked.connect(utils_geometry.geometry_temp_utils_function)
self.buttons["fix_seams"].clicked.connect(utils_geometry.geometry_temp_utils_function)
self.buttons["fix_vertex_order"].clicked.connect(utils_geometry.geometry_temp_utils_function)