#!/usr/bin/env python # -*- coding: utf-8 -*- """ Definition UI Module for Plugin 定义系统UI模块 - 负责显示DNA定义编辑界面和基础操作 基本功能: - LOD, Meshes, Joints, Blendshape, AnimatedMap 加载和刷新 - 写入: 写入关节默认位置,写入几何体,写入蒙皮,写入混合变形目标 - 创建:创建混合变形,绑定蒙皮,取消蒙皮 - 工具:重新定位头部关节,重新定位身体关节,重新定位全身关节,快速创建预设 """ #========================================= 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 from scripts.ui import ui_utils from scripts.utils import utils_definition #========================================== 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 class DefinitionUI(ui_utils.BaseUI): """ 定义系统UI类 - 负责显示DNA定义编辑界面和基础操作 继承自BaseUI类,实现DNA定义相关的UI功能 """ #========================================== INIT ======================================== def __init__(self): """ 初始化定义系统UI 创建主控件和布局,并连接信号和槽 """ super(DefinitionUI, self).__init__() # 创建主控件 self.main_widget = QtWidgets.QWidget() self.main_widget.setObjectName("definitionMainWidget") # 初始化UI self.create_widgets() self.create_layouts() self.create_connections() #========================================= WIDGET ======================================= def create_widgets(self): """ 创建定义系统UI控件 包括按钮、标签、列表等 """ # 标题标签 self.controls["title_label"] = QtWidgets.QLabel(LANG.get("definition_title", "DNA定义")) self.controls["title_label"].setObjectName("definitionTitleLabel") self.controls["title_label"].setAlignment(QtCore.Qt.AlignCenter) # 主分割器 self.splitters["main_splitter"] = QtWidgets.QSplitter(QtCore.Qt.Horizontal) self.splitters["main_splitter"].setObjectName("definitionMainSplitter") # 左侧面板 self.controls["left_panel"] = QtWidgets.QWidget() self.controls["left_panel"].setObjectName("definitionLeftPanel") # 右侧面板 self.controls["right_panel"] = QtWidgets.QWidget() self.controls["right_panel"].setObjectName("definitionRightPanel") # 左侧面板控件 # LODs组 self.controls["lods_group"] = QtWidgets.QGroupBox("LODs") self.controls["lods_group"].setObjectName("lodsGroup") # LODs列表 self.controls["lods_list"] = QtWidgets.QListWidget() self.controls["lods_list"].setObjectName("lodsList") # 定义LOD关联按钮 self.buttons["define_lod_relations"] = QtWidgets.QPushButton(LANG.get("define_lod_relations", "定义LOD关联")) self.buttons["define_lod_relations"].setObjectName("defineLodRelationsButton") # Meshes组 self.controls["meshes_group"] = QtWidgets.QGroupBox("Meshes [000]") self.controls["meshes_group"].setObjectName("meshesGroup") # Meshes列表 self.controls["meshes_list"] = QtWidgets.QListWidget() self.controls["meshes_list"].setObjectName("meshesList") # 创建几何体按钮 self.buttons["create_geometry"] = QtWidgets.QPushButton(LANG.get("create_geometry", "创建几何体")) self.buttons["create_geometry"].setObjectName("createGeometryButton") # 右侧面板控件 # Joints组 self.controls["joints_group"] = QtWidgets.QGroupBox("Joints [000]") self.controls["joints_group"].setObjectName("jointsGroup") # Joints列表 self.controls["joints_list"] = QtWidgets.QListWidget() self.controls["joints_list"].setObjectName("jointsList") # BlendShapes组 self.controls["blendshapes_group"] = QtWidgets.QGroupBox("BlendShapes [000]") self.controls["blendshapes_group"].setObjectName("blendshapesGroup") # BlendShapes列表 self.controls["blendshapes_list"] = QtWidgets.QListWidget() self.controls["blendshapes_list"].setObjectName("blendshapesList") # AnimatedMap组 self.controls["animatedmap_group"] = QtWidgets.QGroupBox("AnimatedMap [000]") self.controls["animatedmap_group"].setObjectName("animatedmapGroup") # AnimatedMap列表 self.controls["animatedmap_list"] = QtWidgets.QListWidget() self.controls["animatedmap_list"].setObjectName("animatedmapList") # 底部工具面板 # 导入部分 self.controls["import_label"] = QtWidgets.QLabel(LANG.get("import", "导入")) self.controls["import_label"].setObjectName("importLabel") self.controls["import_label"].setAlignment(QtCore.Qt.AlignCenter) self.buttons["import_joint_system"] = QtWidgets.QPushButton(LANG.get("import_joint_system", "导入关节系统")) self.buttons["import_joint_system"].setObjectName("importJointSystemButton") self.buttons["import_geometry"] = QtWidgets.QPushButton(LANG.get("import_geometry", "导入几何体")) self.buttons["import_geometry"].setObjectName("importGeometryButton") self.buttons["import_blendshape_target"] = QtWidgets.QPushButton(LANG.get("import_blendshape_target", "导入形状混合目标")) self.buttons["import_blendshape_target"].setObjectName("importBlendshapeTargetButton") self.buttons["import_animated_map"] = QtWidgets.QPushButton(LANG.get("import_animated_map", "导入动画贴图")) self.buttons["import_animated_map"].setObjectName("importAnimatedMapButton") # 创建部分 self.controls["create_label"] = QtWidgets.QLabel(LANG.get("create", "创建")) self.controls["create_label"].setObjectName("createLabel") self.controls["create_label"].setAlignment(QtCore.Qt.AlignCenter) self.buttons["create_neutral_pose"] = QtWidgets.QPushButton(LANG.get("create_neutral_pose", "创建中性姿势")) self.buttons["create_neutral_pose"].setObjectName("createNeutralPoseButton") self.buttons["bind_geometry"] = QtWidgets.QPushButton(LANG.get("bind_geometry", "绑定几何体")) self.buttons["bind_geometry"].setObjectName("bindGeometryButton") self.buttons["take_pose"] = QtWidgets.QPushButton(LANG.get("take_pose", "取消姿势")) self.buttons["take_pose"].setObjectName("takePoseButton") # 工具部分 self.controls["tools_label"] = QtWidgets.QLabel(LANG.get("tools", "工具")) self.controls["tools_label"].setObjectName("toolsLabel") self.controls["tools_label"].setAlignment(QtCore.Qt.AlignCenter) self.buttons["reposition_all_joints"] = QtWidgets.QPushButton(LANG.get("reposition_all_joints", "重新定位所有关节")) self.buttons["reposition_all_joints"].setObjectName("repositionAllJointsButton") self.buttons["reposition_selected_joints"] = QtWidgets.QPushButton(LANG.get("reposition_selected_joints", "重新定位选定关节")) self.buttons["reposition_selected_joints"].setObjectName("repositionSelectedJointsButton") self.buttons["reposition_all_head_joints"] = QtWidgets.QPushButton(LANG.get("reposition_all_head_joints", "重新定位所有头部关节")) self.buttons["reposition_all_head_joints"].setObjectName("repositionAllHeadJointsButton") self.buttons["quick_preset"] = QtWidgets.QPushButton(LANG.get("quick_preset", "快速预设")) self.buttons["quick_preset"].setObjectName("quickPresetButton") self.buttons["unbind_skin"] = QtWidgets.QPushButton(LANG.get("unbind_skin", "取消蒙皮")) # 工具组 self.controls["tools_group"] = QtWidgets.QGroupBox(LANG.get("tools_group", "工具")) self.controls["tools_group"].setObjectName("toolsGroup") # 工具按钮 self.buttons["reposition_head_joints"] = QtWidgets.QPushButton(LANG.get("reposition_head_joints", "重新定位头部关节")) self.buttons["reposition_body_joints"] = QtWidgets.QPushButton(LANG.get("reposition_body_joints", "重新定位身体关节")) self.buttons["reposition_all_joints"] = QtWidgets.QPushButton(LANG.get("reposition_all_joints", "重新定位全身关节")) self.buttons["quick_preset"] = QtWidgets.QPushButton(LANG.get("quick_preset", "快速创建预设")) #========================================= 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.layouts["left_layout"] = QtWidgets.QVBoxLayout(self.controls["left_panel"]) self.layouts["left_layout"].setContentsMargins(0, 0, 0, 0) self.layouts["left_layout"].setSpacing(5) # 左侧分割器 self.splitters["left_splitter"] = QtWidgets.QSplitter(QtCore.Qt.Vertical) self.splitters["left_splitter"].setObjectName("definitionLeftSplitter") self.layouts["left_layout"].addWidget(self.splitters["left_splitter"]) # LODs组布局 self.layouts["lods_layout"] = QtWidgets.QVBoxLayout(self.controls["lods_group"]) self.layouts["lods_layout"].setContentsMargins(5, 5, 5, 5) self.layouts["lods_layout"].setSpacing(5) # 添加LODs列表 self.layouts["lods_layout"].addWidget(self.controls["lods_list"]) # 定义LOD关联按钮 self.layouts["lods_layout"].addWidget(self.buttons["define_lod_relations"]) # Meshes组布局 self.layouts["meshes_layout"] = QtWidgets.QVBoxLayout(self.controls["meshes_group"]) self.layouts["meshes_layout"].setContentsMargins(5, 5, 5, 5) self.layouts["meshes_layout"].setSpacing(5) # 添加Meshes列表 self.layouts["meshes_layout"].addWidget(self.controls["meshes_list"]) # 创建几何体按钮 self.layouts["meshes_layout"].addWidget(self.buttons["create_geometry"]) # 添加到左侧分割器 self.splitters["left_splitter"].addWidget(self.controls["lods_group"]) self.splitters["left_splitter"].addWidget(self.controls["meshes_group"]) # 右侧面板布局 self.layouts["right_layout"] = QtWidgets.QVBoxLayout(self.controls["right_panel"]) self.layouts["right_layout"].setContentsMargins(0, 0, 0, 0) self.layouts["right_layout"].setSpacing(5) # 右侧分割器 self.splitters["right_splitter"] = QtWidgets.QSplitter(QtCore.Qt.Vertical) self.splitters["right_splitter"].setObjectName("definitionRightSplitter") self.layouts["right_layout"].addWidget(self.splitters["right_splitter"]) # Joints组布局 self.layouts["joints_layout"] = QtWidgets.QVBoxLayout(self.controls["joints_group"]) self.layouts["joints_layout"].setContentsMargins(5, 5, 5, 5) self.layouts["joints_layout"].setSpacing(5) # 添加Joints列表 self.layouts["joints_layout"].addWidget(self.controls["joints_list"]) # BlendShapes组布局 self.layouts["blendshapes_layout"] = QtWidgets.QVBoxLayout(self.controls["blendshapes_group"]) self.layouts["blendshapes_layout"].setContentsMargins(5, 5, 5, 5) self.layouts["blendshapes_layout"].setSpacing(5) # 添加BlendShapes列表 self.layouts["blendshapes_layout"].addWidget(self.controls["blendshapes_list"]) # AnimatedMap组布局 self.layouts["animatedmap_layout"] = QtWidgets.QVBoxLayout(self.controls["animatedmap_group"]) self.layouts["animatedmap_layout"].setContentsMargins(5, 5, 5, 5) self.layouts["animatedmap_layout"].setSpacing(5) # 添加AnimatedMap列表 self.layouts["animatedmap_layout"].addWidget(self.controls["animatedmap_list"]) # 添加到右侧分割器 self.splitters["right_splitter"].addWidget(self.controls["joints_group"]) self.splitters["right_splitter"].addWidget(self.controls["blendshapes_group"]) self.splitters["right_splitter"].addWidget(self.controls["animatedmap_group"]) # 底部工具面板 self.layouts["bottom_panel"] = QtWidgets.QHBoxLayout() self.layouts["bottom_panel"].setContentsMargins(0, 10, 0, 0) self.layouts["bottom_panel"].setSpacing(10) # 导入部分布局 self.layouts["import_layout"] = QtWidgets.QVBoxLayout() self.layouts["import_layout"].setSpacing(5) self.layouts["import_layout"].addWidget(self.controls["import_label"]) self.layouts["import_layout"].addWidget(self.buttons["import_joint_system"]) self.layouts["import_layout"].addWidget(self.buttons["import_geometry"]) self.layouts["import_layout"].addWidget(self.buttons["import_blendshape_target"]) self.layouts["import_layout"].addWidget(self.buttons["import_animated_map"]) # 创建部分布局 self.layouts["create_layout"] = QtWidgets.QVBoxLayout() self.layouts["create_layout"].setSpacing(5) self.layouts["create_layout"].addWidget(self.controls["create_label"]) self.layouts["create_layout"].addWidget(self.buttons["create_neutral_pose"]) self.layouts["create_layout"].addWidget(self.buttons["bind_geometry"]) self.layouts["create_layout"].addWidget(self.buttons["take_pose"]) self.layouts["create_layout"].addWidget(self.buttons["unbind_skin"]) # 工具部分布局 self.layouts["tools_layout"] = QtWidgets.QVBoxLayout() self.layouts["tools_layout"].setSpacing(5) self.layouts["tools_layout"].addWidget(self.controls["tools_label"]) self.layouts["tools_layout"].addWidget(self.buttons["reposition_all_joints"]) self.layouts["tools_layout"].addWidget(self.buttons["reposition_selected_joints"]) self.layouts["tools_layout"].addWidget(self.buttons["reposition_all_head_joints"]) self.layouts["tools_layout"].addWidget(self.buttons["quick_preset"]) # 添加三列到底部面板 self.layouts["bottom_panel"].addLayout(self.layouts["import_layout"]) self.layouts["bottom_panel"].addLayout(self.layouts["create_layout"]) self.layouts["bottom_panel"].addLayout(self.layouts["tools_layout"]) # 添加底部面板到主布局 self.layouts["main_layout"].addLayout(self.layouts["bottom_panel"]) # 设置分割器初始大小 # 主分割器左右各半 self.splitters["main_splitter"].setSizes([500, 500]) # 左侧分割器上下各半 self.splitters["left_splitter"].setSizes([250, 250]) # 右侧分割器均匀分配 right_item_height = 1000 // self.splitters["right_splitter"].count() self.splitters["right_splitter"].setSizes([right_item_height] * self.splitters["right_splitter"].count()) # 设置分割器的伸缩因子,确保左右栏能够自动调整宽度 for i in range(self.splitters["main_splitter"].count()): self.splitters["main_splitter"].setStretchFactor(i, 1) # 将左右面板添加到主分割器 self.splitters["main_splitter"].addWidget(self.controls["left_panel"]) self.splitters["main_splitter"].addWidget(self.controls["right_panel"]) #======================================= CONNECTION ===================================== def create_connections(self): """ 连接信号和槽 设置UI控件的交互行为 """ # 左侧面板连接 # LODs列表连接 self.controls["lods_list"].itemClicked.connect(utils_definition.lod_selected) self.controls["lods_list"].itemSelectionChanged.connect(utils_definition.update_lod_selection) # 定义LOD关联按钮连接 self.buttons["define_lod_relations"].clicked.connect(utils_definition.define_lod_relations) # Meshes列表连接 self.controls["meshes_list"].itemClicked.connect(utils_definition.mesh_selected) self.controls["meshes_list"].itemSelectionChanged.connect(utils_definition.update_mesh_selection) # 创建几何体按钮连接 self.buttons["create_geometry"].clicked.connect(utils_definition.create_geometry) # 右侧面板连接 # Joints列表连接 self.controls["joints_list"].itemClicked.connect(utils_definition.joint_selected) self.controls["joints_list"].itemSelectionChanged.connect(utils_definition.update_joint_selection) # BlendShapes列表连接 self.controls["blendshapes_list"].itemClicked.connect(utils_definition.blendshape_selected) self.controls["blendshapes_list"].itemSelectionChanged.connect(utils_definition.update_blendshape_selection) # AnimatedMap列表连接 self.controls["animatedmap_list"].itemClicked.connect(utils_definition.animatedmap_selected) self.controls["animatedmap_list"].itemSelectionChanged.connect(utils_definition.update_animatedmap_selection) # 底部工具面板连接 # 导入部分按钮连接 self.buttons["import_joint_system"].clicked.connect(utils_definition.import_joint_system) self.buttons["import_geometry"].clicked.connect(utils_definition.import_geometry) self.buttons["import_blendshape_target"].clicked.connect(utils_definition.import_blendshape_target) self.buttons["import_animated_map"].clicked.connect(utils_definition.import_animated_map) # 创建部分按钮连接 self.buttons["create_neutral_pose"].clicked.connect(utils_definition.create_neutral_pose) self.buttons["bind_geometry"].clicked.connect(utils_definition.bind_geometry) self.buttons["take_pose"].clicked.connect(utils_definition.take_pose) self.buttons["unbind_skin"].clicked.connect(utils_definition.unbind_skin) # 工具部分按钮连接 self.buttons["reposition_all_joints"].clicked.connect(utils_definition.reposition_all_joints) self.buttons["reposition_selected_joints"].clicked.connect(utils_definition.reposition_selected_joints) self.buttons["reposition_all_head_joints"].clicked.connect(utils_definition.reposition_all_head_joints) self.buttons["quick_preset"].clicked.connect(utils_definition.quick_preset)