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

@@ -166,7 +166,7 @@ We support one-click to correct the pose of the character to the correct pose, a
- Face and panel controllers can be seamlessly switched, use context7;
- https://pointart.oss-cn-hangzhou.aliyuncs.com/wp-content/uploads/2024/06/%E9%9D%A2%E9%83%A8%E6%8E%A7%E5%88%B6%E5%99%A8.mp4, use context7;
- Aiming at the problem that Metahuman's face control panel is not intuitive, we support the generation of a brand-new face controller, which can directly adjust the expression and muscles of the character on the face. If you contact Metahuman controller soon, it will greatly reduce your learning cost.
- Aiming at the problem that Metahuman face control panel is not intuitive, we support the generation of a brand-new face controller, which can directly adjust the expression and muscles of the character on the face. If you contact Metahuman controller soon, it will greatly reduce your learning cost.
#### 1.1.7. Different topological binding

27
Plan.md
View File

@@ -154,13 +154,30 @@ MetaHumanDNAPlugin/
## 进度记录与后续安排
### 2025-05-06 更新
### 2025-05-08 更新
- 基础框架与UI阶段第一阶段已完成95%
- 完成了主要UI模块的创建和基本功能实现
#### 已完成
- 基础框架与UI第一阶段已完成95%
- 主界面与四大核心面板geometry/rigging/behaviour/definition功能与布局基本完善
- 行为面板behaviour.py布局结构已规范化分割器与面板嵌套逻辑已修正交互体验提升
- 多语言映射文件localization.py已补全支持各主要功能区和按钮的中英文切换
- 优化了项目结构,明确了各模块的职责和接口
- 需要进行UI微调与优化包括统一样式、完善交互等
- DNA处理核心模块已初步实现需要进一步完善与测试
- 参考Epic官方MetaHuman DNA Calibration与SuperRigging等插件吸收最佳实践
#### 进行中
- UI微调与优化统一按钮样式、图标、响应式布局
- 多语言支持完善持续补全各模块UI文本映射
- DNA核心功能开发dnalib模块完善、MetaHuman DNA标准兼容、文件导入导出
- 增强UI与Maya交互的稳定性优化性能减少重绘
- 行为、定义、几何等面板的交互细节持续优化
#### 下一步
- 完成所有UI面板的多语言、样式、布局一致性
- 完善DNA文件读写、MetaHuman兼容与一键式流程
- 开发批量处理、自动化绑定与多LOD支持
- 增强文档与测试,持续同步开发进度
---
### 2025-04-30 更新

View File

@@ -14,7 +14,7 @@ TOOL_YEAR = "2025"
TOOL_MOD_FILENAME = f"{TOOL_NAME.lower()}.mod"
TOOL_LANG = "en_US"
TOOL_WSCL_NAME = f"{TOOL_NAME}WorkspaceControl"
TOOL_HELP_URL = f"http://10.72.61.59:3000/ArtGroup/{TOOL_NAME}/wiki"
TOOL_HELP_URL = f"https://gitea.cgnico.com/CGNICO/{TOOL_NAME}/wiki"
# Path Configuration
TOOL_PATH = os.path.dirname(os.path.abspath(__file__)).replace("\\", "/")

View File

@@ -31,8 +31,7 @@ from scripts.ui import behaviour
from scripts.ui import definition
#========================================= LOCALIZATION =====================================
from scripts.ui import localization
LANG = localization.LANG
get_text = localization.get_text
TEXT = localization.TEXT
#=========================================== CONFIG =========================================
import config
TOOL_NAME = config.TOOL_NAME
@@ -111,13 +110,13 @@ class MainWindow(QtWidgets.QWidget):
# 创建功能区域切换按钮组
self.function_buttons = {}
self.function_buttons["geometry"] = QtWidgets.QPushButton(get_text("geometry", "几何体"))
self.function_buttons["geometry"] = QtWidgets.QPushButton(TEXT("geometry", "几何体"))
self.function_buttons["geometry"].setIcon(ui_utils.load_icon("meshes.png"))
self.function_buttons["rigging"] = QtWidgets.QPushButton(get_text("rigging", "绑定"))
self.function_buttons["rigging"] = QtWidgets.QPushButton(TEXT("rigging", "绑定"))
self.function_buttons["rigging"].setIcon(ui_utils.load_icon("configuration.png"))
self.function_buttons["behaviour"] = QtWidgets.QPushButton(get_text("behaviour", "行为"))
self.function_buttons["behaviour"] = QtWidgets.QPushButton(TEXT("behaviour", "行为"))
self.function_buttons["behaviour"].setIcon(ui_utils.load_icon("behaviour.png"))
self.function_buttons["definition"] = QtWidgets.QPushButton(get_text("definition", "定义"))
self.function_buttons["definition"] = QtWidgets.QPushButton(TEXT("definition", "定义"))
self.function_buttons["definition"].setIcon(ui_utils.load_icon("definition.png"))
# 设置按钮样式和属性

View File

@@ -51,6 +51,9 @@ except ImportError:
HAS_QT = False
print("警告: 无法导入Qt模块UI功能将不可用")
import config
TOOL_NAME = config.TOOL_NAME
#===================================== 公共函数 =====================================
def clean_pycache(root_dir):
"""
@@ -411,7 +414,7 @@ class ModuleReloaderUI(QtWidgets.QDialog):
parent = parent or getMayaMainWindow()
super(ModuleReloaderUI, self).__init__(parent)
self.setWindowTitle(f"{TOOL_NAME} - 模块重载工具")
self.setWindowTitle("模块重载工具")
self.setMinimumWidth(600)
self.setMinimumHeight(500)
self.setWindowFlags(self.windowFlags() | QtCore.Qt.WindowStaysOnTopHint)
@@ -427,7 +430,7 @@ class ModuleReloaderUI(QtWidgets.QDialog):
main_layout.setSpacing(10)
# 标题标签
title_label = QtWidgets.QLabel(f"{TOOL_NAME} 模块重载工具")
title_label = QtWidgets.QLabel("模块重载工具")
title_label.setStyleSheet("font-size: 16px; font-weight: bold;")
main_layout.addWidget(title_label)

View File

@@ -17,8 +17,8 @@ Behaviour 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
@@ -57,51 +57,29 @@ 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 BehaviourUI(ui_utils.BaseUI):
"""
行为系统UI类 - 负责显示角色行为编辑界面和基础操作
继承自BaseUI类实现行为系统相关的UI功能
"""
# 类变量,存储单例实例
_instance = None
@classmethod
def get_instance(cls):
"""
获取BehaviourUI的单例实例
Returns:
BehaviourUI: 单例实例如果不存在则返回None
"""
return cls._instance
#========================================== INIT ========================================
def __init__(self, parent=None):
"""
初始化行为系统UI
"""
super(BehaviourUI, self).__init__() # 不传递parent参数给BaseUI
# 设置单例实例
BehaviourUI._instance = self
super().__init__(parent)
# 创建主控件
self.main_widget = QtWidgets.QWidget(parent)
self.main_widget = QtWidgets.QWidget()
self.main_widget.setObjectName("behaviourMainWidget")
# 初始化控件、布局和按钮字典
self.controls = {}
self.layouts = {}
self.buttons = {}
self.splitters = {}
# 创建UI组件
self.create_widgets()
self.create_layouts()
self.create_connections()
# 更新UI文本
self.update_language()
# 设置全局样式,确保所有控件都没有最小宽度限制
self.main_widget.setStyleSheet("""
QWidget { min-width: 0px; }
@@ -118,7 +96,7 @@ class BehaviourUI(ui_utils.BaseUI):
包括标题标签、搜索框、控制列表、滑块等
"""
# 标题标签
self.controls["title_label"] = QtWidgets.QLabel(get_text("behaviour_title", "行为系统"))
self.controls["title_label"] = QtWidgets.QLabel(TEXT("behaviour_title", "行为系统"))
self.controls["title_label"].setObjectName("behaviourTitleLabel")
self.controls["title_label"].setAlignment(QtCore.Qt.AlignCenter)
self.controls["title_label"].setStyleSheet("font-size: 14px; font-weight: bold; padding: 5px;")
@@ -141,7 +119,7 @@ class BehaviourUI(ui_utils.BaseUI):
# 搜索框
self.controls["search_input"] = QtWidgets.QLineEdit()
self.controls["search_input"].setObjectName("searchInput")
self.controls["search_input"].setPlaceholderText(get_text("search", "搜索..."))
self.controls["search_input"].setPlaceholderText(TEXT("search", "搜索..."))
self.controls["search_input"].setFixedHeight(25)
# 控制列表
@@ -193,27 +171,27 @@ class BehaviourUI(ui_utils.BaseUI):
self.buttons["page_6"].setCheckable(True)
# 左下角Range按钮
self.buttons["range_minus"] = QtWidgets.QPushButton(get_text(" Range - ", " 范围 - "))
self.buttons["range_minus"] = QtWidgets.QPushButton(TEXT(" Range - ", " 范围 - "))
self.buttons["range_minus"].setObjectName("rangeMinusButton")
self.buttons["range_minus"].setIcon(ui_utils.load_icon("behaviour.png"))
self.buttons["range_minus"].setMinimumWidth(0)
self.buttons["range_plus"] = QtWidgets.QPushButton(get_text(" Range + ", " 范围 + "))
self.buttons["range_plus"] = QtWidgets.QPushButton(TEXT(" Range + ", " 范围 + "))
self.buttons["range_plus"].setObjectName("rangePlusButton")
self.buttons["range_plus"].setIcon(ui_utils.load_icon("behaviour.png"))
self.buttons["range_plus"].setMinimumWidth(0)
# 左侧面板控件 - Raw Control
self.controls["raw_control_group"] = QtWidgets.QGroupBox(get_text("Raw Control", "原始控制"))
self.controls["raw_control_group"] = QtWidgets.QGroupBox(TEXT("Raw Control", "原始控制"))
self.controls["raw_control_group"].setObjectName("rawControlGroup")
self.controls["raw_control_group"].setTitle(get_text("Raw Control", "原始控制"))
self.controls["raw_control_group"].setTitle(TEXT("Raw Control", "原始控制"))
self.controls["raw_control_group"].setFixedHeight(25)
# 右侧面板控件 - Related BlendShapes
self.controls["blendshapes_group"] = QtWidgets.QGroupBox(get_text("Related BlendShapes", "相关BlendShapes"))
self.controls["blendshapes_group"] = QtWidgets.QGroupBox(TEXT("Related BlendShapes", "相关BlendShapes"))
self.controls["blendshapes_group"].setObjectName("blendshapesGroup")
self.controls["blendshapes_group"].setTitle(get_text("Related BlendShapes", "相关BlendShapes"))
self.controls["blendshapes_group"].setTitle(TEXT("Related BlendShapes", "相关BlendShapes"))
self.controls["blendshapes_group"].setFixedHeight(25)
# BlendShapes列表
@@ -239,60 +217,60 @@ class BehaviourUI(ui_utils.BaseUI):
self.controls["bs_slider_all_check"].setObjectName("bsSliderAllCheck")
# 右下角BS Range按钮
self.buttons["bs_range_minus"] = QtWidgets.QPushButton(get_text(" Range - ", " 范围 - "))
self.buttons["bs_range_minus"] = QtWidgets.QPushButton(TEXT(" Range - ", " 范围 - "))
self.buttons["bs_range_minus"].setObjectName("bsRangeMinusButton")
self.buttons["bs_range_minus"].setIcon(ui_utils.load_icon("behaviour.png"))
self.buttons["bs_range_minus"].setMinimumWidth(0)
self.buttons["bs_range_plus"] = QtWidgets.QPushButton(get_text(" Range + ", " 范围 + "))
self.buttons["bs_range_plus"] = QtWidgets.QPushButton(TEXT(" Range + ", " 范围 + "))
self.buttons["bs_range_plus"].setObjectName("bsRangePlusButton")
self.buttons["bs_range_plus"].setIcon(ui_utils.load_icon("behaviour.png"))
self.buttons["bs_range_plus"].setMinimumWidth(0)
# BlendShape操作按钮
self.buttons["flip_target"] = QtWidgets.QPushButton(get_text("Flip Target", "翻转目标"))
self.buttons["flip_target"] = QtWidgets.QPushButton(TEXT("Flip Target", "翻转目标"))
self.buttons["flip_target"].setObjectName("flipTargetButton")
self.buttons["flip_target"].setIcon(ui_utils.load_icon("mirrorL.png"))
self.buttons["mirror_target"] = QtWidgets.QPushButton(get_text("Mirror Target", "镜像目标"))
self.buttons["mirror_target"] = QtWidgets.QPushButton(TEXT("Mirror Target", "镜像目标"))
self.buttons["mirror_target"].setObjectName("mirrorTargetButton")
self.buttons["mirror_target"].setIcon(ui_utils.load_icon("mirror.png"))
self.buttons["find_flip_target"] = QtWidgets.QPushButton(get_text("Find Flip Target", "查找翻转目标"))
self.buttons["find_flip_target"] = QtWidgets.QPushButton(TEXT("Find Flip Target", "查找翻转目标"))
self.buttons["find_flip_target"].setObjectName("findFlipTargetButton")
self.buttons["find_flip_target"].setIcon(ui_utils.load_icon("mirrorR.png"))
self.buttons["add_blendshape"] = QtWidgets.QPushButton(get_text("Add BlendShape", "添加BlendShape"))
self.buttons["add_blendshape"] = QtWidgets.QPushButton(TEXT("Add BlendShape", "添加BlendShape"))
self.buttons["add_blendshape"].setObjectName("addBlendshapeButton")
self.buttons["add_blendshape"].setIcon(ui_utils.load_icon("blendShape.png"))
self.buttons["delete_blendshape"] = QtWidgets.QPushButton(get_text("Delete BlendShape", "删除BlendShape"))
self.buttons["delete_blendshape"] = QtWidgets.QPushButton(TEXT("Delete BlendShape", "删除BlendShape"))
self.buttons["delete_blendshape"].setObjectName("deleteBlendshapeButton")
self.buttons["delete_blendshape"].setIcon(ui_utils.load_icon("blendShape.png"))
self.buttons["batch_blendshape"] = QtWidgets.QPushButton(get_text("Batch BlendShape", "批量BlendShape"))
self.buttons["batch_blendshape"] = QtWidgets.QPushButton(TEXT("Batch BlendShape", "批量BlendShape"))
self.buttons["batch_blendshape"].setObjectName("batchBlendshapeButton")
self.buttons["batch_blendshape"].setIcon(ui_utils.load_icon("blendShape.png"))
self.buttons["bs_range_minus"] = QtWidgets.QPushButton(get_text(" Range - ", " 范围 - "))
self.buttons["bs_range_minus"] = QtWidgets.QPushButton(TEXT(" Range - ", " 范围 - "))
self.buttons["bs_range_minus"].setObjectName("bsRangeMinusButton")
self.buttons["bs_range_minus"].setIcon(ui_utils.load_icon("behaviour.png"))
self.buttons["bs_range_minus"].setMinimumWidth(0)
self.buttons["bs_range_plus"] = QtWidgets.QPushButton(get_text(" Range + ", " 范围 + "))
self.buttons["bs_range_plus"] = QtWidgets.QPushButton(TEXT(" Range + ", " 范围 + "))
self.buttons["bs_range_plus"].setObjectName("bsRangePlusButton")
self.buttons["bs_range_plus"].setIcon(ui_utils.load_icon("behaviour.png"))
self.buttons["bs_range_plus"].setMinimumWidth(0)
self.buttons["rebuild_select"] = QtWidgets.QPushButton(get_text("Rebuild Select", "重建选择"))
self.buttons["rebuild_select"] = QtWidgets.QPushButton(TEXT("Rebuild Select", "重建选择"))
self.buttons["rebuild_select"].setObjectName("rebuildSelectButton")
self.buttons["rebuild_select"].setIcon(ui_utils.load_icon("loading.png"))
self.buttons["reposition_joints"] = QtWidgets.QPushButton(get_text("Reposition Joints", "重新定位关节"))
self.buttons["reposition_joints"] = QtWidgets.QPushButton(TEXT("Reposition Joints", "重新定位关节"))
self.buttons["reposition_joints"].setObjectName("repositionJointsButton")
self.buttons["reposition_joints"].setIcon(ui_utils.load_icon("loading.png"))
self.buttons["blend_select"] = QtWidgets.QPushButton(get_text("Blend Select", "混合选择"))
self.buttons["blend_select"] = QtWidgets.QPushButton(TEXT("Blend Select", "混合选择"))
self.buttons["blend_select"].setObjectName("blendSelectButton")
self.buttons["blend_select"].setIcon(ui_utils.load_icon("loading.png"))
@@ -314,64 +292,64 @@ class BehaviourUI(ui_utils.BaseUI):
self.controls["bottom_slider_all_check"].setObjectName("bottomSliderAllCheck")
# 底部标签页按钮
self.buttons["tab_psd"] = QtWidgets.QPushButton(get_text("PSD", "PSD"))
self.buttons["tab_psd"] = QtWidgets.QPushButton(TEXT("PSD", "PSD"))
self.buttons["tab_psd"].setIcon(ui_utils.load_icon("psd.png"))
self.buttons["tab_psd"].setObjectName("tabPsdButton")
self.buttons["tab_psd"].setCheckable(True)
self.buttons["tab_psd"].setChecked(True)
self.buttons["tab_bse"] = QtWidgets.QPushButton(get_text("BSE", "BSE"))
self.buttons["tab_bse"] = QtWidgets.QPushButton(TEXT("BSE", "BSE"))
self.buttons["tab_bse"].setIcon(ui_utils.load_icon("blendShape.png"))
self.buttons["tab_bse"].setObjectName("tabBseButton")
self.buttons["tab_bse"].setCheckable(True)
self.buttons["tab_bse"].setChecked(True)
self.buttons["tab_key"] = QtWidgets.QPushButton(get_text("KEY", "KEY"))
self.buttons["tab_key"] = QtWidgets.QPushButton(TEXT("KEY", "KEY"))
self.buttons["tab_key"].setIcon(ui_utils.load_icon("setKeyOnAnim.png"))
self.buttons["tab_key"].setObjectName("tabKeyButton")
self.buttons["tab_key"].setCheckable(True)
self.buttons["tab_key"].setChecked(True)
self.buttons["tab_mir"] = QtWidgets.QPushButton(get_text("MIR", "MIR"))
self.buttons["tab_mir"] = QtWidgets.QPushButton(TEXT("MIR", "MIR"))
self.buttons["tab_mir"].setIcon(ui_utils.load_icon("mirrorR.png"))
self.buttons["tab_mir"].setObjectName("tabMirButton")
self.buttons["tab_mir"].setCheckable(True)
self.buttons["tab_mir"].setChecked(True)
self.buttons["tab_ark"] = QtWidgets.QPushButton(get_text("ARK", "ARK"))
self.buttons["tab_ark"] = QtWidgets.QPushButton(TEXT("ARK", "ARK"))
self.buttons["tab_ark"].setIcon(ui_utils.load_icon("ARKit52.png"))
self.buttons["tab_ark"].setObjectName("tabArkButton")
self.buttons["tab_ark"].setCheckable(True)
self.buttons["tab_ark"].setChecked(True)
self.buttons["tab_ctr"] = QtWidgets.QPushButton(get_text("CTR", "CTR"))
self.buttons["tab_ctr"] = QtWidgets.QPushButton(TEXT("CTR", "CTR"))
self.buttons["tab_ctr"].setIcon(ui_utils.load_icon("ctrl_hide.png"))
self.buttons["tab_ctr"].setObjectName("tabCtrButton")
self.buttons["tab_ctr"].setCheckable(True)
self.buttons["tab_ctr"].setChecked(True)
# 底部功能按钮
self.buttons["reset_default_expression"] = QtWidgets.QPushButton(get_text("Reset Default", "重置默认"))
self.buttons["reset_default_expression"] = QtWidgets.QPushButton(TEXT("Reset Default", "重置默认"))
self.buttons["reset_default_expression"].setIcon(ui_utils.load_icon("reset.png"))
self.buttons["reset_default_expression"].setObjectName("resetDefaultExpressionButton")
self.buttons["find_select_expression"] = QtWidgets.QPushButton(get_text("Find Select", "查找选择"))
self.buttons["find_select_expression"] = QtWidgets.QPushButton(TEXT("Find Select", "查找选择"))
self.buttons["find_select_expression"].setIcon(ui_utils.load_icon("expressions_current.png"))
self.buttons["find_select_expression"].setObjectName("findSelectExpressionButton")
self.buttons["write_current_expressions"] = QtWidgets.QPushButton(get_text("Write Current", "写入当前"))
self.buttons["write_current_expressions"] = QtWidgets.QPushButton(TEXT("Write Current", "写入当前"))
self.buttons["write_current_expressions"].setIcon(ui_utils.load_icon("expression.png"))
self.buttons["write_current_expressions"].setObjectName("writeCurrentExpressionsButton")
self.buttons["controller_find"] = QtWidgets.QPushButton(get_text("Controller Find", "控制器查找"))
self.buttons["controller_find"] = QtWidgets.QPushButton(TEXT("Controller Find", "控制器查找"))
self.buttons["controller_find"].setIcon(ui_utils.load_icon("controller.png"))
self.buttons["controller_find"].setObjectName("controllerFindButton")
self.buttons["select_associated_joint"] = QtWidgets.QPushButton(get_text("Select Joint", "选择关节"))
self.buttons["select_associated_joint"] = QtWidgets.QPushButton(TEXT("Select Joint", "选择关节"))
self.buttons["select_associated_joint"].setIcon(ui_utils.load_icon("out_joint.png"))
self.buttons["select_associated_joint"].setObjectName("selectAssociatedJointButton")
self.buttons["write_find_mirror"] = QtWidgets.QPushButton(get_text("Find Mirror", "查找镜像"))
self.buttons["write_find_mirror"] = QtWidgets.QPushButton(TEXT("Find Mirror", "查找镜像"))
self.buttons["write_find_mirror"].setIcon(ui_utils.load_icon("mirror.png"))
self.buttons["write_find_mirror"].setObjectName("writeFindMirrorButton")
@@ -417,7 +395,7 @@ class BehaviourUI(ui_utils.BaseUI):
self.layouts["left_content_layout"].setSpacing(5)
# 添加标题标签
left_title = QtWidgets.QLabel(get_text("Raw Control", "原始控制"))
left_title = QtWidgets.QLabel(TEXT("Raw Control", "原始控制"))
left_title.setStyleSheet("font-weight: bold;")
self.layouts["left_content_layout"].addWidget(left_title)
@@ -481,7 +459,7 @@ class BehaviourUI(ui_utils.BaseUI):
self.layouts["right_content_layout"].setSpacing(5)
# 添加标题标签
right_title = QtWidgets.QLabel(get_text("Related BlendShapes", "相关BlendShapes"))
right_title = QtWidgets.QLabel(TEXT("Related BlendShapes", "相关BlendShapes"))
right_title.setStyleSheet("font-weight: bold;")
self.layouts["right_content_layout"].addWidget(right_title)

View File

@@ -11,8 +11,8 @@ Definition 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
@@ -51,8 +51,7 @@ 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 DefinitionUI(ui_utils.BaseUI):
"""
@@ -64,27 +63,19 @@ class DefinitionUI(ui_utils.BaseUI):
"""
初始化定义系统UI
"""
super(DefinitionUI, self).__init__() # 不传递parent参数给BaseUI
# 设置单例实例
DefinitionUI._instance = self
super().__init__(parent)
# 创建主控件
self.main_widget = QtWidgets.QWidget(parent)
self.main_widget = QtWidgets.QWidget()
self.main_widget.setObjectName("definitionMainWidget")
# 初始化控件、布局和按钮字典
self.controls = {}
self.layouts = {}
self.buttons = {}
self.splitters = {}
# 创建UI组件
self.create_widgets()
self.create_layouts()
self.create_connections()
# 注意:移除了这里的分割器元素添加代码
# 更新UI文本
self.update_language()
#========================================= WIDGET =======================================
def create_widgets(self):
@@ -93,7 +84,7 @@ class DefinitionUI(ui_utils.BaseUI):
包括按钮、标签、列表等
"""
# 标题标签 - 使用HTML格式化标题
title_text = f"<h4 style='margin:0;padding:5px;'>{get_text('definition_title', 'DNA定义')}</h4>"
title_text = f"<h4 style='margin:0;padding:5px;'>{TEXT('definition_title', 'DNA定义')}</h4>"
self.controls["title_label"] = QtWidgets.QLabel(title_text)
self.controls["title_label"].setObjectName("definitionTitleLabel")
self.controls["title_label"].setAlignment(QtCore.Qt.AlignCenter)
@@ -124,7 +115,7 @@ class DefinitionUI(ui_utils.BaseUI):
self.controls["lods_list"].setObjectName("lodsList")
# 定义LOD关联按钮
self.buttons["define_lod_relations"] = QtWidgets.QPushButton(get_text("define_lod_relations", "定义LOD关联"))
self.buttons["define_lod_relations"] = QtWidgets.QPushButton(TEXT("define_lod_relations", "定义LOD关联"))
self.buttons["define_lod_relations"].setIcon(ui_utils.load_icon("layerEditor.png"))
self.buttons["define_lod_relations"].setObjectName("defineLodRelationsButton")
@@ -137,7 +128,7 @@ class DefinitionUI(ui_utils.BaseUI):
self.controls["meshes_list"].setObjectName("meshesList")
# 创建几何体按钮
self.buttons["create_geometry"] = QtWidgets.QPushButton(get_text("create_geometry", "创建几何体"))
self.buttons["create_geometry"] = QtWidgets.QPushButton(TEXT("create_geometry", "创建几何体"))
self.buttons["create_geometry"].setIcon(ui_utils.load_icon("polyCube.png"))
self.buttons["create_geometry"].setObjectName("createGeometryButton")
@@ -168,61 +159,61 @@ class DefinitionUI(ui_utils.BaseUI):
# 底部工具面板
# 写入部分
self.controls["write_label"] = QtWidgets.QLabel(get_text("Write", "写入"))
self.controls["write_label"] = QtWidgets.QLabel(TEXT("Write", "写入"))
self.controls["write_label"].setObjectName("WriteLabel")
self.controls["write_label"].setAlignment(QtCore.Qt.AlignCenter)
self.buttons["write_neutral_pose_joint_position"] = QtWidgets.QPushButton(get_text("Write Neutral Pose Joint Position", "写入中性Pose关节位置"))
self.buttons["write_neutral_pose_joint_position"] = QtWidgets.QPushButton(TEXT("Write Neutral Pose Joint Position", "写入中性Pose关节位置"))
self.buttons["write_neutral_pose_joint_position"].setIcon(ui_utils.load_icon("HIKCharacterToolBodyPart.png"))
self.buttons["write_neutral_pose_joint_position"].setObjectName("WriteNeutralPoseJointPositionButton")
self.buttons["write_geometry"] = QtWidgets.QPushButton(get_text("Write Geometry", "写入几何体"))
self.buttons["write_geometry"] = QtWidgets.QPushButton(TEXT("Write Geometry", "写入几何体"))
self.buttons["write_geometry"].setIcon(ui_utils.load_icon("polyCube.png"))
self.buttons["write_geometry"].setObjectName("WriteGeometryButton")
self.buttons["write_skin_weight"] = QtWidgets.QPushButton(get_text("Write Skin Weight", "写入蒙皮权重"))
self.buttons["write_skin_weight"] = QtWidgets.QPushButton(TEXT("Write Skin Weight", "写入蒙皮权重"))
self.buttons["write_skin_weight"].setIcon(ui_utils.load_icon("paintSkinWeights.png"))
self.buttons["write_skin_weight"].setObjectName("WriteSkinWeightButton")
self.buttons["write_blendshape_target"] = QtWidgets.QPushButton(get_text("Write Blendshape Target", "写入BS对象"))
self.buttons["write_blendshape_target"] = QtWidgets.QPushButton(TEXT("Write Blendshape Target", "写入BS对象"))
self.buttons["write_blendshape_target"].setIcon(ui_utils.load_icon("blendShape.png"))
self.buttons["write_blendshape_target"].setObjectName("WriteBlendshapeTargetButton")
# 创建部分
self.controls["create_label"] = QtWidgets.QLabel(get_text("Create", "创建"))
self.controls["create_label"] = QtWidgets.QLabel(TEXT("Create", "创建"))
self.controls["create_label"].setObjectName("CreateLabel")
self.controls["create_label"].setAlignment(QtCore.Qt.AlignCenter)
self.buttons["create_blendshapes_for_mesh"] = QtWidgets.QPushButton(get_text("Create Blendshapes For Mesh", "为模型创建Blendshape"))
self.buttons["create_blendshapes_for_mesh"] = QtWidgets.QPushButton(TEXT("Create Blendshapes For Mesh", "为模型创建Blendshape"))
self.buttons["create_blendshapes_for_mesh"].setIcon(ui_utils.load_icon("blendShapeEditor.png"))
self.buttons["create_blendshapes_for_mesh"].setObjectName("CreateBlendshapeForMeshButton")
self.buttons["create_skin_for_mesh"] = QtWidgets.QPushButton(get_text("Create Skin For Mesh", "为模型创建绑定蒙皮"))
self.buttons["create_skin_for_mesh"] = QtWidgets.QPushButton(TEXT("Create Skin For Mesh", "为模型创建绑定蒙皮"))
self.buttons["create_skin_for_mesh"].setIcon(ui_utils.load_icon("smoothSkin.png"))
self.buttons["create_skin_for_mesh"].setObjectName("CreateSkinForMeshButton")
self.buttons["unbind_skin_for_mesh"] = QtWidgets.QPushButton(get_text("Unbind Skin For Mesh", "为模型取消绑定蒙皮"))
self.buttons["unbind_skin_for_mesh"] = QtWidgets.QPushButton(TEXT("Unbind Skin For Mesh", "为模型取消绑定蒙皮"))
self.buttons["unbind_skin_for_mesh"].setIcon(ui_utils.load_icon("detachSkin.png"))
self.buttons["unbind_skin_for_mesh"].setObjectName("UnbindSkinForMeshButton")
# 工具部分
self.controls["tools_label"] = QtWidgets.QGroupBox(get_text("Tools", "工具"))
self.controls["tools_label"] = QtWidgets.QGroupBox(TEXT("Tools", "工具"))
self.controls["tools_label"].setObjectName("ToolsLabel")
self.controls["tools_label"].setAlignment(QtCore.Qt.AlignCenter)
self.buttons["new_head_netural_joint_transform"] = QtWidgets.QPushButton(get_text("New Head Netural Joint Transform", "重新定位头部关节"))
self.buttons["new_head_netural_joint_transform"] = QtWidgets.QPushButton(TEXT("New Head Netural Joint Transform", "重新定位头部关节"))
self.buttons["new_head_netural_joint_transform"].setIcon(ui_utils.load_icon("HIKCharacterToolSkeleton.png"))
self.buttons["new_head_netural_joint_transform"].setObjectName("NewHeadNeturalJointTransformButton")
self.buttons["new_body_netural_joint_transform"] = QtWidgets.QPushButton(get_text("New Body Netural Joint Transform", "重新定位身体关节"))
self.buttons["new_body_netural_joint_transform"] = QtWidgets.QPushButton(TEXT("New Body Netural Joint Transform", "重新定位身体关节"))
self.buttons["new_body_netural_joint_transform"].setIcon(ui_utils.load_icon("HIKCharacterToolSkeleton.png"))
self.buttons["new_body_netural_joint_transform"].setObjectName("NewBodyNeturalJointTransformButton")
self.buttons["new_netural_joint_transform"] = QtWidgets.QPushButton(get_text("New Netural Joint Transform", "重新定位全身关节"))
self.buttons["new_netural_joint_transform"] = QtWidgets.QPushButton(TEXT("New Netural Joint Transform", "重新定位全身关节"))
self.buttons["new_netural_joint_transform"].setIcon(ui_utils.load_icon("HIKCharacterToolSkeleton.png"))
self.buttons["new_netural_joint_transform"].setObjectName("NewNeturalJointTransformButton")
self.buttons["quick_create_preset"] = QtWidgets.QPushButton(get_text("Quick Create Preset", "快速创建预设"))
self.buttons["quick_create_preset"] = QtWidgets.QPushButton(TEXT("Quick Create Preset", "快速创建预设"))
self.buttons["quick_create_preset"].setIcon(ui_utils.load_icon("QR_QuickRigTool.png"))
self.buttons["quick_create_preset"].setObjectName("QuickCreatePreset")
@@ -324,7 +315,7 @@ class DefinitionUI(ui_utils.BaseUI):
self.layouts["bottom_panel"].setSpacing(10)
# 写入部分QGroupBox
self.controls["write_group"] = QtWidgets.QGroupBox(get_text("Write", "写入"))
self.controls["write_group"] = QtWidgets.QGroupBox(TEXT("Write", "写入"))
self.controls["write_group"].setObjectName("writeGroup")
self.layouts["write_layout"] = QtWidgets.QVBoxLayout()
self.layouts["write_layout"].setSpacing(5)
@@ -336,7 +327,7 @@ class DefinitionUI(ui_utils.BaseUI):
self.controls["write_group"].setLayout(self.layouts["write_layout"])
# 创建部分QGroupBox
self.controls["create_group"] = QtWidgets.QGroupBox(get_text("Create", "创建"))
self.controls["create_group"] = QtWidgets.QGroupBox(TEXT("Create", "创建"))
self.controls["create_group"].setObjectName("createGroup")
self.layouts["create_layout"] = QtWidgets.QVBoxLayout()
self.layouts["create_layout"].setSpacing(5)
@@ -347,7 +338,7 @@ class DefinitionUI(ui_utils.BaseUI):
self.controls["create_group"].setLayout(self.layouts["create_layout"])
# 工具部分QGroupBox
self.controls["tools_group"] = QtWidgets.QGroupBox(get_text("Tools", "工具"))
self.controls["tools_group"] = QtWidgets.QGroupBox(TEXT("Tools", "工具"))
self.controls["tools_group"].setObjectName("toolsGroup")
self.layouts["tools_layout"] = QtWidgets.QVBoxLayout()
self.layouts["tools_layout"].setSpacing(5)

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)

View File

@@ -13,124 +13,6 @@ current_language = config.TOOL_LANG # 默认使用中文
# 语言字典
LANG = {
"en_US": {
# 主界面
"geometry": "Geometry",
"rigging": "Rigging",
"behaviour": "Behaviour",
"definition": "Definition",
# 几何体模块
"geometry_title": "Geometry",
"clean": " Clean ",
"load": "Load mesh",
"clear_all_models": " Clean all models",
"add_model": "Add Model",
"remove_model": "Remove Model",
"duplicate_model": "Duplicate Model",
"model_properties": "Model Properties",
"model_tools": "Model Tools",
"name": "Name",
"enter_model_name": "Enter Model Name",
"type": "Type",
"visible": "Visible",
"apply": "Apply",
"reset": "Reset",
"topology_structure": "Topology Structure",
"select_lod": "Select LOD",
"all": "All",
"create_lod": "Create LOD",
"separate_model": "Separate Model",
"generate_face_components": "Generate Face Components",
"fix_point_order": "Fix point order",
"fix_normals": "Fix normal",
"fix_vertex_order": "Fix vertex order",
"fix_seams": "Fix seams",
"standardize_naming": "Standardize Naming",
"optimize_scene": "Optimize Scene",
"auto_group": "Auto Group",
"create_custom_lod": "Create Custom LOD",
"import_lod": "Import LOD",
"export_lod": "Export LOD",
"search": "Search...",
# 绑定模块
"rigging_title": "Rigging System",
"presets": "Presets",
"assets": "Assets",
"descriptor": "Descriptor",
"project_path": "Project Path",
"Presets DNA:": "Presets DNA:",
"gender": "Gender",
"age": "Age",
"translation_unit": "Translation Unit",
"rotation_unit": "Rotation Unit",
"coordinate_system": "Coordinate System",
"lod_count": "LOD Count",
"archetype": "Archetype",
"import_skeleton": "Import Skeleton",
"build_rigging": "Build Rigging",
"remove_all": "Remove All",
# 行为模块
"behaviour_title": "Behaviour System",
"search": "Search...",
" Range - ": " Range - ",
" Range + ": " Range + ",
"Raw Control": "Raw Control",
"Related BlendShapes": "Related BlendShapes",
"Add": "Add",
"Delete": "Delete",
"Batch": "Batch",
"Rebuild": "Rebuild",
"Reposition": "Reposition",
"Blend": "Blend",
"Flip Target": "Flip Target",
"Mirror Target": "Mirror Target",
"Find Flip Target": "Find Flip Target",
"Add BlendShape": "Add BlendShape",
"Delete BlendShape": "Delete BlendShape",
"Batch BlendShape": "Batch BlendShape",
"Rebuild Select": "Rebuild Select",
"Reposition Joints": "Reposition Joints",
"Blend Select": "Blend Select",
"Reset Default": "Reset Default",
"Find Select": "Find Select",
"Write Current": "Write Current",
"Controller Find": "Controller Find",
"Select Joint": "Select Joint",
"Find Mirror": "Find Mirror",
# 定义模块
"definition_title": "Definition System",
"lods": "LODs",
"meshes": "Meshes",
"bones": "Bones",
"name_pattern": "Name Pattern",
"expression": "Expression",
"add_lod": "Add LOD",
"remove_lod": "Remove LOD",
"duplicate_lod": "Duplicate LOD",
"add_mesh": "Add Mesh",
"remove_mesh": "Remove Mesh",
"duplicate_mesh": "Duplicate Mesh",
"add_bone": "Add Bone",
"remove_bone": "Remove Bone",
"duplicate_bone": "Duplicate Bone",
"import_definition": "Import Definition",
"export_definition": "Export Definition",
# 工具栏
"Save DNA": "Save DNA",
"Open DNA": "Open DNA",
"Create RL4 node": "Create RL4 Node",
"Delete RL4 node": "Delete RL4 Node",
"Import skin": "Import Skin",
"Export skin": "Export Skin",
"Copy skin": "Copy Skin",
"Switch language": "Switch Language",
"Help": "Help"
},
"zh_CN": {
# 主界面
"geometry": "几何体",
@@ -140,55 +22,46 @@ LANG = {
# 几何体模块
"geometry_title": "几何模型",
"clean": " 清 理 ",
"load": " 加 载 ",
"clear_all_models": " 清理所有模型",
"add_model": "添加模型",
"remove_model": "移除模型",
"duplicate_model": "复制模型",
"model_properties": "模型属性",
"model_tools": "模型工具",
"name": "名称",
"enter_model_name": "输入模型名称",
"type": "类型",
"visible": "可见",
"apply": "应用",
"reset": "重置",
"load": " 加 载 ",
"load_model": "加载模型",
"auto_load_meshes": "自动加载模型",
"standardized_naming": "标准化命名",
"automatic_grouping": "自动分组",
"clear": " 清 理 ",
"clear_all_models": "清理所有模型",
"model_tools": "模型工具",
"topology_structure": "拓扑结构",
"select_lod": "选择LOD",
"all": "全部",
"create_lod": "创建LOD",
"separate_model": "模型分离",
"generate_face_components": "生成面部配件",
"fix_point_order": "修复点序",
"fix_normals": "修复法线",
"fix_vertex_order": "修复点序",
"fix_seams": "修复接缝",
"standardize_naming": "标准化命名",
"optimize_scene": "优化场景",
"auto_group": "自动分组",
"create_custom_lod": "创建自定义LOD",
"import_lod": "导入LOD",
"export_lod": "导出LOD",
"search": "搜索...",
# 绑定模块
"rigging_title": "绑定系统",
"presets": "预设",
"assets": "资源",
"descriptor": "描述器",
"project_path": "项目路径",
"export_presets": "导出预设",
"import_presets": "导入预设",
"assets": "资产",
"project_path": "项目路径:",
"Presets DNA:": "预设 DNA:",
"gender": "性别",
"age": "年龄",
"translation_unit": "平移单位",
"rotation_unit": "旋转单位",
"coordinate_system": "坐标系统",
"lod_count": "LOD数量",
"archetype": "原型",
"descriptor": "描述",
"name": "名称:",
"archetype": "原型:",
"gender": "性别:",
"age": "年龄:",
"translation_unit": "平移单位:",
"rotation_unit": "旋转单位:",
"coordinate_system": "坐标系统:",
"lod_count": "LOD数量:",
"remove_all": "移除全部",
"import_skeleton": "导入骨骼",
"build_rigging": "创建绑定",
"remove_all": "移除全部",
# 行为模块
"behaviour_title": "行为系统",
@@ -221,23 +94,21 @@ LANG = {
# 定义模块
"definition_title": "定义系统",
"lods": "级别细节",
"meshes": "网格",
"bones": "骨骼",
"name_pattern": "命名模式",
"expression": "表情",
"add_lod": "添加LOD",
"remove_lod": "移除LOD",
"duplicate_lod": "复制LOD",
"add_mesh": "添加网格",
"remove_mesh": "移除网格",
"duplicate_mesh": "复制网格",
"add_bone": "添加骨骼",
"remove_bone": "移除骨骼",
"duplicate_bone": "复制骨骼",
"import_definition": "导入定义",
"export_definition": "导出定义",
"define_lod_relations": "定义LOD关联",
"create_geometry": "创建几何体",
"Write Neutral Pose Joint Position": "写入中性Pose关节位置",
"Write Geometry": "写入几何体",
"Write Skin Weight": "写入蒙皮权重",
"Write Blendshape Target": "写入BS对象",
"Create Blendshapes For Mesh": "为模型创建Blendshape",
"Create Skin For Mesh": "为模型创建绑定蒙皮",
"Unbind Skin For Mesh": "为模型取消绑定蒙皮",
"Tools": "工具",
"New Head Netural Joint Transform": "重新定位头部关节",
"New Body Netural Joint Transform": "重新定位身体关节",
"New Netural Joint Transform": "重新定位全身关节",
"Quick Create Preset": "快速创建预设",
# 工具栏
"保存DNA": "保存DNA",
"打开DNA": "打开DNA",
@@ -248,10 +119,117 @@ LANG = {
"复制蒙皮": "复制蒙皮",
"切换语言": "切换语言",
"帮助": "帮助"
},
"en_US": {
# Main Interface
"geometry": "Geometry",
"rigging": "Rigging",
"behaviour": "Behaviour",
"definition": "Definition",
# Geometry Module
"geometry_title": "Geometry Model",
"enter_model_name": "Enter Model Name",
"load": "Load",
"load_model": "Load Model",
"auto_load_meshes": "Auto Load Meshes",
"standardized_naming": "Standardized Naming",
"automatic_grouping": "Automatic Grouping",
"clear": "Clear",
"clear_all_models": "Clear All Models",
"model_tools": "Model Tools",
"topology_structure": "Topology Structure",
"select_lod": "Select LOD",
"all": "All",
"create_lod": "Create LOD",
"separate_model": "Separate Model",
"generate_face_components": "Generate Face Components",
"fix_normals": "Fix Normals",
"fix_vertex_order": "Fix Vertex Order",
"fix_seams": "Fix Seams",
"optimize_scene": "Optimize Scene",
# Rigging Module
"rigging_title": "Rigging System",
"presets": "Presets",
"export_presets": "Export Presets",
"import_presets": "Import Presets",
"assets": "Assets",
"project_path": "Project Path:",
"Presets DNA:": "Presets DNA:",
"descriptor": "Descriptor",
"name": "Name:",
"archetype": "Archetype:",
"gender": "Gender:",
"age": "Age:",
"translation_unit": "Translation Unit:",
"rotation_unit": "Rotation Unit:",
"coordinate_system": "Coordinate System:",
"lod_count": "LOD Count:",
"remove_all": "Remove All",
"import_skeleton": "Import Skeleton",
"build_rigging": "Build Rigging",
# Behaviour Module
"behaviour_title": "Behaviour System",
"search": "Search...",
" Range - ": " Range - ",
" Range + ": " Range + ",
"Raw Control": "Raw Control",
"Related BlendShapes": "Related BlendShapes",
"Add": "Add",
"Delete": "Delete",
"Batch": "Batch",
"Rebuild": "Rebuild",
"Reposition": "Reposition",
"Blend": "Blend",
"Flip Target": "Flip Target",
"Mirror Target": "Mirror Target",
"Find Flip Target": "Find Flip Target",
"Add BlendShape": "Add BlendShape",
"Delete BlendShape": "Delete BlendShape",
"Batch BlendShape": "Batch BlendShape",
"Rebuild Select": "Rebuild Select",
"Reposition Joints": "Reposition Joints",
"Blend Select": "Blend Select",
"Reset Default": "Reset Default",
"Find Select": "Find Select",
"Write Current": "Write Current",
"Controller Find": "Controller Find",
"Select Joint": "Select Joint",
"Find Mirror": "Find Mirror",
# Definition Module
"definition_title": "Definition System",
"define_lod_relations": "Define LOD Relations",
"create_geometry": "Create Geometry",
"Write Neutral Pose Joint Position": "Write Neutral Pose Joint Position",
"Write Geometry": "Write Geometry",
"Write Skin Weight": "Write Skin Weight",
"Write Blendshape Target": "Write BlendShape Target",
"Create Blendshapes For Mesh": "Create BlendShapes For Mesh",
"Create Skin For Mesh": "Create Skin For Mesh",
"Unbind Skin For Mesh": "Unbind Skin For Mesh",
"Tools": "Tools",
"New Head Netural Joint Transform": "Relocate Head Joint",
"New Body Netural Joint Transform": "Relocate Body Joint",
"New Netural Joint Transform": "Relocate All Joints",
"Quick Create Preset": "Quick Create Preset",
# Toolbar
"保存DNA": "Save DNA",
"打开DNA": "Open DNA",
"创建RL4节点": "Create RL4 Node",
"删除RL4节点": "Delete RL4 Node",
"导入蒙皮": "Import Skin",
"导出蒙皮": "Export Skin",
"复制蒙皮": "Copy Skin",
"切换语言": "Switch Language",
"帮助": "Help"
}
}
def get_text(key, default=None):
def TEXT(key, default=None):
"""
获取当前语言的文本

View File

@@ -14,8 +14,8 @@ Rigging 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
@@ -54,8 +54,7 @@ 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 RiggingUI(ui_utils.BaseUI):
"""
@@ -63,21 +62,13 @@ class RiggingUI(ui_utils.BaseUI):
继承自BaseUI类实现绑定系统相关的UI功能
"""
#========================================== INIT ========================================
def __init__(self):
def __init__(self, parent=None):
"""
初始化绑定系统UI
创建主控件和布局,并连接信号和槽
"""
super(RiggingUI, self).__init__()
# 初始化字典
self.controls = {}
self.layouts = {}
self.buttons = {}
self.splitters = {}
self.inputs = {}
self.labels = {}
super().__init__(parent)
# 创建主控件
self.main_widget = QtWidgets.QWidget()
self.main_widget.setObjectName("riggingMainWidget")
@@ -86,6 +77,9 @@ class RiggingUI(ui_utils.BaseUI):
self.create_widgets()
self.create_layouts()
self.create_connections()
# 更新UI文本
self.update_language()
#========================================= WIDGET =======================================
def create_widgets(self):
@@ -94,7 +88,7 @@ class RiggingUI(ui_utils.BaseUI):
包括按钮、标签、列表等
"""
# 标题标签 - 使用HTML格式化标题
title_text = f"<h4 style='margin:0;padding:5px;'>{get_text('rigging_title', '骨骼绑定')}</h4>"
title_text = f"<h4 style='margin:0;padding:5px;'>{TEXT('rigging_title', '骨骼绑定')}</h4>"
self.controls["title_label"] = QtWidgets.QLabel(title_text)
self.controls["title_label"].setObjectName("riggingTitleLabel")
self.controls["title_label"].setAlignment(QtCore.Qt.AlignCenter)
@@ -109,7 +103,7 @@ class RiggingUI(ui_utils.BaseUI):
self.controls["presets_panel"].setObjectName("presetsPanel")
# Presets 组
self.controls["presets_group"] = QtWidgets.QGroupBox(get_text("presets", "Presets"))
self.controls["presets_group"] = QtWidgets.QGroupBox(TEXT("presets", "Presets"))
self.controls["presets_group"].setObjectName("presetsGroup")
# 创建预设显示区域
@@ -190,12 +184,12 @@ class RiggingUI(ui_utils.BaseUI):
self.controls["presets_slider"].setValue(50)
# 导出预设按钮
self.buttons["export_presets"] = QtWidgets.QPushButton(get_text("export_presets", "导出预设"))
self.buttons["export_presets"] = QtWidgets.QPushButton(TEXT("export_presets", "导出预设"))
self.buttons["export_presets"].setObjectName("exportPresetsButton")
self.buttons["export_presets"].setIcon(ui_utils.load_icon("export"))
# 导入预设按钮
self.buttons["import_presets"] = QtWidgets.QPushButton(get_text("import_presets", "导入预设"))
self.buttons["import_presets"] = QtWidgets.QPushButton(TEXT("import_presets", "导入预设"))
self.buttons["import_presets"].setObjectName("importPresetsButton")
self.buttons["import_presets"].setIcon(ui_utils.load_icon("import"))
@@ -210,11 +204,11 @@ class RiggingUI(ui_utils.BaseUI):
self.controls["assets_panel"].setObjectName("assetsPanel")
# Assets 组
self.controls["assets_group"] = QtWidgets.QGroupBox(get_text("assets", "Assets"))
self.controls["assets_group"] = QtWidgets.QGroupBox(TEXT("assets", "资产"))
self.controls["assets_group"].setObjectName("assetsGroup")
# 项目路径标签和输入框
self.controls["project_path_label"] = QtWidgets.QLabel(get_text("project_path", "项目路径:"))
self.controls["project_path_label"] = QtWidgets.QLabel(TEXT("project_path", "项目路径:"))
self.controls["project_path_label"].setObjectName("projectPathLabel")
self.controls["project_path_input"] = QtWidgets.QLineEdit()
@@ -229,7 +223,7 @@ class RiggingUI(ui_utils.BaseUI):
self.buttons["browse_path"].setFixedWidth(100)
# Presets DNA 标签和输入框
self.controls["presets_dna_label"] = QtWidgets.QLabel(get_text("Presets DNA:", "预设 DNA:"))
self.controls["presets_dna_label"] = QtWidgets.QLabel(TEXT("Presets DNA:", "预设 DNA:"))
self.controls["presets_dna_label"].setObjectName("presetsDnaLabel")
self.controls["presets_dna_input"] = QtWidgets.QLineEdit()
@@ -247,18 +241,18 @@ class RiggingUI(ui_utils.BaseUI):
self.controls["descriptor_panel"].setObjectName("descriptorPanel")
# Descriptor 组
self.controls["descriptor_group"] = QtWidgets.QGroupBox(get_text("descriptor", "Descriptor"))
self.controls["descriptor_group"] = QtWidgets.QGroupBox(TEXT("descriptor", "描述"))
self.controls["descriptor_group"].setObjectName("descriptorGroup")
# 名称标签和输入框
self.controls["name_label"] = QtWidgets.QLabel(get_text("name", "名称:"))
self.controls["name_label"] = QtWidgets.QLabel(TEXT("name", "名称:"))
self.controls["name_label"].setObjectName("nameLabel")
self.controls["name_input"] = QtWidgets.QLineEdit()
self.controls["name_input"].setObjectName("nameInput")
# 原型标签和下拉框
self.controls["archetype_label"] = QtWidgets.QLabel(get_text("archetype", "原型:"))
self.controls["archetype_label"] = QtWidgets.QLabel(TEXT("archetype", "原型:"))
self.controls["archetype_label"].setObjectName("archetypeLabel")
self.controls["archetype_combo"] = QtWidgets.QComboBox()
@@ -268,7 +262,7 @@ class RiggingUI(ui_utils.BaseUI):
self.controls["archetype_combo"].addItem("african")
# 性别标签和下拉框
self.controls["gender_label"] = QtWidgets.QLabel(get_text("gender", "性别:"))
self.controls["gender_label"] = QtWidgets.QLabel(TEXT("gender", "性别:"))
self.controls["gender_label"].setObjectName("genderLabel")
self.controls["gender_combo"] = QtWidgets.QComboBox()
@@ -277,7 +271,7 @@ class RiggingUI(ui_utils.BaseUI):
self.controls["gender_combo"].addItem("male")
# 年龄标签和输入框
self.controls["age_label"] = QtWidgets.QLabel(get_text("age", "年龄:"))
self.controls["age_label"] = QtWidgets.QLabel(TEXT("age", "年龄:"))
self.controls["age_label"].setObjectName("ageLabel")
self.controls["age_spinner"] = QtWidgets.QSpinBox()
@@ -287,7 +281,7 @@ class RiggingUI(ui_utils.BaseUI):
self.controls["age_spinner"].setValue(24)
# 平移单位标签和下拉框
self.controls["translation_unit_label"] = QtWidgets.QLabel(get_text("translation_unit", "平移单位:"))
self.controls["translation_unit_label"] = QtWidgets.QLabel(TEXT("translation_unit", "平移单位:"))
self.controls["translation_unit_label"].setObjectName("translationUnitLabel")
self.controls["translation_unit_combo"] = QtWidgets.QComboBox()
@@ -297,7 +291,7 @@ class RiggingUI(ui_utils.BaseUI):
self.controls["translation_unit_combo"].addItem("m")
# 旋转单位标签和下拉框
self.controls["rotation_unit_label"] = QtWidgets.QLabel(get_text("rotation_unit", "旋转单位:"))
self.controls["rotation_unit_label"] = QtWidgets.QLabel(TEXT("rotation_unit", "旋转单位:"))
self.controls["rotation_unit_label"].setObjectName("rotationUnitLabel")
self.controls["rotation_unit_combo"] = QtWidgets.QComboBox()
@@ -306,7 +300,7 @@ class RiggingUI(ui_utils.BaseUI):
self.controls["rotation_unit_combo"].addItem("radians")
# 坐标系统标签和下拉框
self.controls["coordinate_system_label"] = QtWidgets.QLabel(get_text("coordinate_system", "坐标系统:"))
self.controls["coordinate_system_label"] = QtWidgets.QLabel(TEXT("coordinate_system", "坐标系统:"))
self.controls["coordinate_system_label"].setObjectName("coordinateSystemLabel")
self.controls["coordinate_system_combo"] = QtWidgets.QComboBox()
@@ -315,7 +309,7 @@ class RiggingUI(ui_utils.BaseUI):
self.controls["coordinate_system_combo"].addItem("ZAxisUp")
# LOD数量标签和输入框
self.controls["lod_count_label"] = QtWidgets.QLabel(get_text("lod_count", "LOD数量:"))
self.controls["lod_count_label"] = QtWidgets.QLabel(TEXT("lod_count", "LOD数量:"))
self.controls["lod_count_label"].setObjectName("lodCountLabel")
self.controls["lod_count_spinner"] = QtWidgets.QSpinBox()
@@ -329,17 +323,17 @@ class RiggingUI(ui_utils.BaseUI):
self.controls["bottom_buttons_panel"].setObjectName("bottomButtonsPanel")
# 删除所有按钮
self.buttons["remove_all"] = QtWidgets.QPushButton(get_text("remove_all", "删除所有"))
self.buttons["remove_all"] = QtWidgets.QPushButton(TEXT("remove_all", "删除全部"))
self.buttons["remove_all"].setObjectName("removeAllButton")
self.buttons["remove_all"].setIcon(ui_utils.load_icon("delete.png"))
# 导入骨骼按钮
self.buttons["import_skeleton"] = QtWidgets.QPushButton(get_text("import_skeleton", "导入骨骼"))
self.buttons["import_skeleton"] = QtWidgets.QPushButton(TEXT("import_skeleton", "导入骨骼"))
self.buttons["import_skeleton"].setObjectName("importSkeletonButton")
self.buttons["import_skeleton"].setIcon(ui_utils.load_icon("HIKCharacterToolSkeleton.png"))
# 生成绑定按钮
self.buttons["build_rigging"] = QtWidgets.QPushButton(get_text("build_rigging", "生成绑定"))
self.buttons["build_rigging"] = QtWidgets.QPushButton(TEXT("build_rigging", "创建绑定"))
self.buttons["build_rigging"].setObjectName("buildRiggingButton")
self.buttons["build_rigging"].setIcon(ui_utils.load_icon("HIKcreateControlRig.png"))

View File

@@ -1,5 +1,4 @@
/* 插件样式表 */
/* 作者: Virtuos Games */
/* 版本: Alpha v1.0.0 */
/* ==================== 全局样式 ==================== */

View File

@@ -13,8 +13,8 @@ Toolbar UI Module for Plugin
- 删除RL4节点用于切换DNA编辑的状态
"""
#========================================= 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
@@ -28,7 +28,6 @@ import sys
import os
from scripts.ui import ui_utils
from scripts.utils import utils_toolbar
from scripts.ui.localization import get_text
#========================================== CONFIG ========================================
import config
TOOL_NAME = config.TOOL_NAME
@@ -54,36 +53,20 @@ TOOL_WIDTH = config.TOOL_WIDTH
TOOL_HEIGHT = config.TOOL_HEIGHT
#========================================= LOCATION =======================================
from scripts.ui import localization
LANG = localization.LANG
TEXT = localization.TEXT
class ToolbarUI(ui_utils.BaseUI):
"""
工具栏UI类 - 负责显示工具栏界面和基础操作
继承自BaseUI类实现工具栏相关的UI功能
"""
# 类变量,存储单例实例
_instance = None
@classmethod
def get_instance(cls):
"""
获取ToolbarUI的单例实例
Returns:
ToolbarUI: 单例实例如果不存在则返回None
"""
return cls._instance
#========================================== INIT ========================================
def __init__(self):
def __init__(self, parent=None):
"""
初始化工具栏UI
创建主控件和布局,并连接信号和槽
"""
super(ToolbarUI, self).__init__()
# 设置单例实例
ToolbarUI._instance = self
super().__init__(parent)
# 创建主控件
self.main_widget = QtWidgets.QWidget()
@@ -135,7 +118,7 @@ class ToolbarUI(ui_utils.BaseUI):
checkable: 是否可选中
"""
button = QtWidgets.QPushButton()
button.setToolTip(get_text(tooltip, tooltip))
button.setToolTip(TEXT(tooltip, tooltip))
# 构建图标完整路径
icon_path = os.path.join(ICONS_PATH, icon_name)
@@ -146,7 +129,7 @@ class ToolbarUI(ui_utils.BaseUI):
button.setIconSize(QtCore.QSize(24, 24))
else:
# 如果图标不存在,使用文字
button.setText(get_text(tooltip, tooltip))
button.setText(TEXT(tooltip, tooltip))
button.setObjectName(f"{tooltip.replace(' ', '_').lower()}_button")
button.setFixedSize(32, 32)

View File

@@ -6,8 +6,8 @@ UI Utilities Module for Plugin
UI工具模块 - 提供UI相关的通用函数
"""
#========================================= 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
@@ -47,16 +47,15 @@ TOOL_HEIGHT = config.TOOL_HEIGHT
#========================================= LOCATION =======================================
from scripts.ui import localization
LANG = localization.LANG
TEXT = localization.TEXT
#============================================ UI BASE ==========================================
class BaseUI(object):
class BaseUI(QtWidgets.QWidget):
"""
UI基类
所有UI面板的基类提供通用的UI功能
"""
def __init__(self):
"""初始化UI基类"""
def __init__(self, parent=None):
super().__init__(parent)
# 初始化字典
self.controls = {}
self.layouts = {}
@@ -64,7 +63,6 @@ class BaseUI(object):
self.splitters = {}
self.inputs = {}
self.labels = {}
# 创建主控件
self.main_widget = None
@@ -82,10 +80,23 @@ class BaseUI(object):
def update_language(self):
"""
新所有UI文本到当前语言
递归刷新所有UI控件文本,支持多语言切换
"""
if self.main_widget:
update_ui_texts(self.main_widget)
from scripts.ui import localization
# 批量刷新注册字典中的控件
for group in [self.controls, self.labels, self.buttons, getattr(self, 'inputs', {}), getattr(self, 'splitters', {})]:
for key, widget in group.items():
# QLabel/QPushButton/QCheckBox/QRadioButton等
if hasattr(widget, 'setText'):
widget.setText(TEXT(key, widget.text() if hasattr(widget, 'text') else ""))
# QLineEdit等
elif hasattr(widget, 'setPlaceholderText'):
widget.setPlaceholderText(TEXT(key, widget.placeholderText() if hasattr(widget, 'placeholderText') else ""))
# 递归刷新所有自定义子UI即BaseUI子类
for child in self.findChildren(QtWidgets.QWidget):
if child is not self and hasattr(child, 'update_language') and callable(child.update_language):
child.update_language()
#============================================ UI HELPERS ==========================================
def connect_ui_signals(ui_instance, signal_mapping):
@@ -268,7 +279,7 @@ def update_ui_texts(widget):
for lang in ["zh_CN", "en_US"]:
for key, text in localization.LANG.get(lang, {}).items():
if text == current_text:
widget.setText(localization.get_text(key, current_text))
widget.setText(TEXT(key, current_text))
break
# 更新按钮文本和工具提示
@@ -279,7 +290,7 @@ def update_ui_texts(widget):
for lang in ["zh_CN", "en_US"]:
for key, text in localization.LANG.get(lang, {}).items():
if text == current_text:
widget.setText(localization.get_text(key, current_text))
widget.setText(TEXT(key, current_text))
break
# 更新工具提示
@@ -288,7 +299,7 @@ def update_ui_texts(widget):
for lang in ["zh_CN", "en_US"]:
for key, text in localization.LANG.get(lang, {}).items():
if text == current_tip:
widget.setToolTip(localization.get_text(key, current_tip))
widget.setToolTip(TEXT(key, current_tip))
break
# 递归处理所有子控件

View File

@@ -44,7 +44,7 @@ TOOL_WIDTH = config.TOOL_WIDTH
TOOL_HEIGHT = config.TOOL_HEIGHT
# Localization
from scripts.ui import localization
LANG = localization.LANG
TEXT = localization.TEXT
#========================================== FUNCTIONS ========================================
@@ -448,10 +448,10 @@ def update_raw_slider_value(value):
normalized_value = value / 100.0
# 获取UI实例并更新显示
from scripts.ui.behaviour import BehaviourUI
ui_instance = BehaviourUI.get_instance()
if ui_instance and hasattr(ui_instance, 'controls'):
ui_instance.controls["raw_slider_value"].setText(f"{normalized_value:.3f}")
from scripts.ui import behaviour
behaviour_ui = behaviour.BehaviourUI.get_instance()
if behaviour_ui and hasattr(behaviour_ui, 'controls'):
behaviour_ui.controls["raw_slider_value"].setText(f"{normalized_value:.3f}")
# 更新控制值
update_control_value(value)
@@ -472,10 +472,10 @@ def update_bs_slider_value(value):
normalized_value = value / 100.0
# 获取UI实例并更新显示
from scripts.ui.behaviour import BehaviourUI
ui_instance = BehaviourUI.get_instance()
if ui_instance and hasattr(ui_instance, 'controls'):
ui_instance.controls["bs_slider_value"].setText(f"{normalized_value:.3f}")
from scripts.ui import behaviour
behaviour_ui = behaviour.BehaviourUI.get_instance()
if behaviour_ui and hasattr(behaviour_ui, 'controls'):
behaviour_ui.controls["bs_slider_value"].setText(f"{normalized_value:.3f}")
# 更新BlendShape值
update_blendshape_value(value)
@@ -496,10 +496,10 @@ def update_bottom_slider_value(value):
normalized_value = value / 100.0
# 获取UI实例并更新显示
from scripts.ui.behaviour import BehaviourUI
ui_instance = BehaviourUI.get_instance()
if ui_instance and hasattr(ui_instance, 'controls'):
ui_instance.controls["bottom_slider_value"].setText(f"{normalized_value:.3f}")
from scripts.ui import behaviour
behaviour_ui = behaviour.BehaviourUI.get_instance()
if behaviour_ui and hasattr(behaviour_ui, 'controls'):
behaviour_ui.controls["bottom_slider_value"].setText(f"{normalized_value:.3f}")
# 更新主值
update_main_value(value)

View File

@@ -44,7 +44,7 @@ TOOL_WIDTH = config.TOOL_WIDTH
TOOL_HEIGHT = config.TOOL_HEIGHT
# Localization
from scripts.ui import localization
LANG = localization.LANG
TEXT = localization.TEXT
#========================================== FUNCTIONS ========================================
# 左侧面板功能

View File

@@ -44,7 +44,7 @@ TOOL_WIDTH = config.TOOL_WIDTH
TOOL_HEIGHT = config.TOOL_HEIGHT
# Localization
from scripts.ui import localization
LANG = localization.LANG
TEXT = localization.TEXT
#========================================== FUNCTIONS ========================================
# 左侧面板功能
@@ -439,15 +439,15 @@ def clean():
# 确认删除
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", "")
title=TEXT("confirm_delete", "确认删除"),
message=TEXT("delete_lod_confirm", f"确定要删除{lod_name}吗?"),
button=[TEXT("yes", ""), TEXT("no", "")],
defaultButton=TEXT("no", ""),
cancelButton=TEXT("no", ""),
dismissString=TEXT("no", "")
)
if result == LANG.get("yes", ""):
if result == TEXT("yes", ""):
# 删除与该LOD相关的所有模型
nodes_to_delete = cmds.ls(f"{lod_name}_*")
if nodes_to_delete:
@@ -548,7 +548,7 @@ def separate_model():
# 获取当前选中的模型
selected_models = cmds.ls(selection=True, type="transform")
if not selected_models:
cmds.warning(LANG.get("no_model_selected", "未选中模型"))
cmds.warning(TEXT("no_model_selected", "未选中模型"))
return False
# 对每个选中的模型进行分离
@@ -572,7 +572,7 @@ def fix_normals():
# 获取当前选中的模型
selected_models = cmds.ls(selection=True, type="transform")
if not selected_models:
cmds.warning(LANG.get("no_model_selected", "未选中模型"))
cmds.warning(TEXT("no_model_selected", "未选中模型"))
return False
# 对每个选中的模型修复法线
@@ -626,7 +626,7 @@ def modify_topology():
# 获取当前选中的模型
selected_models = cmds.ls(selection=True, type="transform")
if not selected_models:
cmds.warning(LANG.get("no_model_selected", "未选中模型"))
cmds.warning(TEXT("no_model_selected", "未选中模型"))
return False
# 切换到多边形编辑模式
@@ -649,7 +649,7 @@ def generate_face_components():
# 获取当前选中的模型
selected_models = cmds.ls(selection=True, type="transform")
if not selected_models:
cmds.warning(LANG.get("no_model_selected", "未选中模型"))
cmds.warning(TEXT("no_model_selected", "未选中模型"))
return False
# 生成眉毛
@@ -676,7 +676,7 @@ def generate_uvs():
# 获取当前选中的模型
selected_models = cmds.ls(selection=True, type="transform")
if not selected_models:
cmds.warning(LANG.get("no_model_selected", "未选中模型"))
cmds.warning(TEXT("no_model_selected", "未选中模型"))
return False
# 为每个选中的模型生成UV

View File

@@ -44,7 +44,7 @@ TOOL_WIDTH = config.TOOL_WIDTH
TOOL_HEIGHT = config.TOOL_HEIGHT
# Localization
from scripts.ui import localization
LANG = localization.LANG
TEXT = localization.TEXT
#========================================== GLOBALS ========================================
# 存储当前选中的关节和控制器信息

View File

@@ -39,10 +39,7 @@ TOOL_WIDTH = config.TOOL_WIDTH
TOOL_HEIGHT = config.TOOL_HEIGHT
# Localization
from scripts.ui import localization
LANG = localization.LANG
# 添加全局变量记录当前语言
current_language = "zh_CN" # 默认使用中文
TEXT = localization.TEXT
#========================================== FUNCTIONS ========================================
@@ -57,7 +54,7 @@ def save_dna():
fileFilter="DNA Files (*.dna);;All Files (*.*)",
dialogStyle=2,
fileMode=0,
caption=LANG.get("save_dna", "保存DNA文件")
caption=TEXT("save_dna", "保存DNA文件")
)
if file_path and len(file_path) > 0:
@@ -77,7 +74,7 @@ def open_dna():
fileFilter="DNA Files (*.dna);;All Files (*.*)",
dialogStyle=2,
fileMode=1,
caption=LANG.get("open_dna", "打开DNA文件")
caption=TEXT("open_dna", "打开DNA文件")
)
if file_path and len(file_path) > 0:
@@ -123,7 +120,7 @@ def import_skin():
fileFilter="Skin Files (*.skin);;XML Files (*.xml);;All Files (*.*)",
dialogStyle=2,
fileMode=1,
caption=LANG.get("import_skin", "导入蒙皮")
caption=TEXT("import_skin", "导入蒙皮")
)
if file_path and len(file_path) > 0:
@@ -143,7 +140,7 @@ def export_skin():
fileFilter="Skin Files (*.skin);;XML Files (*.xml);;All Files (*.*)",
dialogStyle=2,
fileMode=0,
caption=LANG.get("export_skin", "导出蒙皮")
caption=TEXT("export_skin", "导出蒙皮")
)
if file_path and len(file_path) > 0:
@@ -174,8 +171,8 @@ def show_help():
try:
# 打开帮助文档或显示帮助对话框
help_dialog = QtWidgets.QMessageBox()
help_dialog.setWindowTitle(LANG.get("help_title", "帮助"))
help_dialog.setText(LANG.get("help_message", "该插件是一个用于自定义MetaHuman的Maya插件。\n\n详细信息请参考文档。"))
help_dialog.setWindowTitle(TEXT("help_title", "帮助"))
help_dialog.setText(TEXT("help_message", "该插件是一个用于自定义MetaHuman的Maya插件。\n\n详细信息请参考文档。"))
help_dialog.setStandardButtons(QtWidgets.QMessageBox.Ok)
help_dialog.exec_()
except Exception as e:
@@ -302,10 +299,10 @@ def show_help():
webbrowser.open(config.TOOL_HELP_URL)
else:
cmds.confirmDialog(
title=LANG.get("help", "帮助"),
message=LANG.get("help_not_available", "帮助文档暂不可用"),
button=[LANG.get("ok", "确定")],
defaultButton=LANG.get("ok", "确定")
title=TEXT("help", "帮助"),
message=TEXT("help_not_available", "帮助文档暂不可用"),
button=[TEXT("ok", "确定")],
defaultButton=TEXT("ok", "确定")
)
except Exception as e:
print(f"显示帮助信息时出错: {e}")
@@ -360,15 +357,12 @@ def toggle_language():
"""
from scripts.ui import localization
import config
from ui.Qt import QtWidgets
from scripts.ui.Qt import QtWidgets
# 使用localization模块来切换语言
new_language = localization.switch_language()
# 更新配置
config.TOOL_LANG = new_language
# 尝试更新已有窗口的语言,而不重启窗口
try:
# 查找主窗口
main_window = None
@@ -376,37 +370,33 @@ def toggle_language():
if widget.objectName() == f"{config.TOOL_NAME}MainWindow" and isinstance(widget, QtWidgets.QWidget):
main_window = widget
break
if main_window:
# 更新主窗口标题
main_window.setWindowTitle(f"{config.TOOL_NAME} {config.TOOL_VERSION}")
# 获取各个UI实例并更新语言
from scripts.ui import geometry, rigging, behaviour, definition, toolbar
# 更新各个模块的UI
if hasattr(geometry, 'GeometryUI') and geometry.GeometryUI.get_instance():
geometry.GeometryUI.get_instance().update_language()
if hasattr(rigging, 'RiggingUI') and rigging.RiggingUI.get_instance():
rigging.RiggingUI.get_instance().update_language()
if hasattr(behaviour, 'BehaviourUI') and behaviour.BehaviourUI.get_instance():
behaviour.BehaviourUI.get_instance().update_language()
if hasattr(definition, 'DefinitionUI') and definition.DefinitionUI.get_instance():
definition.DefinitionUI.get_instance().update_language()
# 更新工具栏
if hasattr(toolbar, 'ToolbarUI') and hasattr(main_window, 'toolbar_ui'):
main_window.toolbar_ui.update_language()
# 遍历主窗口的所有子控件,批量动态更新语言
for child in main_window.findChildren(QtWidgets.QWidget):
# 只要有update_language方法就调用
if hasattr(child, 'update_language') and callable(child.update_language):
try:
child.update_language()
except Exception as e:
print(f"更新语言失败: {child}: {e}")
# 更新功能按钮文字
if hasattr(main_window, 'function_buttons'):
for key, button in main_window.function_buttons.items():
button.setText(localization.get_text(key))
button.setText(localization.TEXT(key))
print(f"语言已切换到: {new_language}")
# 切换语言后强制重载主窗口保证所有UI和控件100%刷新
from scripts.Main import main
for widget in QtWidgets.QApplication.allWidgets():
if widget.objectName() == f"{config.TOOL_NAME}MainWindow" and isinstance(widget, QtWidgets.QWidget):
widget.close()
main()
return
except Exception as e:
print(f"动态更新语言失败,将重启窗口: {e}")