648 lines
35 KiB
Python
648 lines
35 KiB
Python
#!/usr/bin/env python
|
||
# -*- coding: utf-8 -*-
|
||
|
||
"""
|
||
Behaviour UI Module for Plugin
|
||
行为系统UI模块 - 负责显示角色行为编辑界面和基础操作
|
||
|
||
基本功能:
|
||
- Blendshape自动加载,刷新,筛选
|
||
- 次级Blendshape自动加载,刷新,筛选
|
||
- Blendshape批量导出和导入
|
||
- Blendshape范围编辑
|
||
- Blendshape镜像
|
||
- Blendshape查找翻转目标
|
||
- 表情控制器还原默认表情
|
||
- 查找选择表情
|
||
- 控制面板查找
|
||
"""
|
||
#========================================= IMPORT =========================================
|
||
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
|
||
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_behaviour
|
||
#========================================== 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
|
||
TOOL_WIDTH = config.TOOL_WIDTH
|
||
TOOL_HEIGHT = config.TOOL_HEIGHT
|
||
#========================================= LOCATION =======================================
|
||
from scripts.ui import localization
|
||
TEXT = localization.TEXT
|
||
|
||
class BehaviourUI(ui_utils.BaseUI):
|
||
"""
|
||
行为系统UI类 - 负责显示角色行为编辑界面和基础操作
|
||
继承自BaseUI类,实现行为系统相关的UI功能
|
||
"""
|
||
#========================================== INIT ========================================
|
||
def __init__(self, parent=None):
|
||
super().__init__(parent)
|
||
|
||
# 创建主控件
|
||
self.main_widget = QtWidgets.QWidget()
|
||
self.main_widget.setObjectName("behaviourMainWidget")
|
||
|
||
# 创建UI组件
|
||
self.create_widgets()
|
||
self.create_layouts()
|
||
self.create_connections()
|
||
|
||
# 更新UI文本
|
||
self.update_language()
|
||
|
||
# 设置全局样式,确保所有控件都没有最小宽度限制
|
||
self.main_widget.setStyleSheet("""
|
||
QWidget { min-width: 0px; }
|
||
QPushButton { min-width: 0px; }
|
||
QLabel { min-width: 0px; }
|
||
QListWidget { min-width: 0px; }
|
||
QGroupBox { min-width: 0px; }
|
||
QSlider { min-width: 0px; }
|
||
""")
|
||
|
||
def create_widgets(self):
|
||
"""
|
||
创建行为系统UI控件
|
||
包括标题标签、搜索框、控制列表、滑块等
|
||
"""
|
||
# 标题标签
|
||
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;")
|
||
|
||
# 主分割器 - 关键设置
|
||
self.splitters["main_splitter"] = QtWidgets.QSplitter(QtCore.Qt.Horizontal)
|
||
self.splitters["main_splitter"].setObjectName("behaviourMainSplitter")
|
||
self.splitters["main_splitter"].setHandleWidth(6) # 设置分割器手柄宽度
|
||
self.splitters["main_splitter"].setChildrenCollapsible(True) # 允许子部件折叠 - 关键设置
|
||
self.splitters["main_splitter"].setOpaqueResize(True) # 实时显示调整效果,更丝滑
|
||
|
||
# 左侧面板 - Raw Control
|
||
self.controls["left_panel"] = QtWidgets.QWidget()
|
||
self.controls["left_panel"].setObjectName("behaviourLeftPanel")
|
||
|
||
# 右侧面板 - BlendShapes
|
||
self.controls["right_panel"] = QtWidgets.QWidget()
|
||
self.controls["right_panel"].setObjectName("behaviourRightPanel")
|
||
|
||
# 搜索框
|
||
self.controls["search_input"] = QtWidgets.QLineEdit()
|
||
self.controls["search_input"].setObjectName("searchInput")
|
||
self.controls["search_input"].setPlaceholderText(TEXT("search", "搜索..."))
|
||
self.controls["search_input"].setFixedHeight(25)
|
||
|
||
# 控制列表
|
||
self.controls["control_list"] = QtWidgets.QListWidget()
|
||
self.controls["control_list"].setObjectName("controlList")
|
||
|
||
# 底部滑块
|
||
self.controls["raw_slider"] = QtWidgets.QSlider(QtCore.Qt.Horizontal)
|
||
self.controls["raw_slider"].setObjectName("rawSlider")
|
||
self.controls["raw_slider"].setMinimum(0)
|
||
self.controls["raw_slider"].setMaximum(100)
|
||
self.controls["raw_slider"].setValue(0)
|
||
self.controls["raw_slider"].setFixedHeight(20)
|
||
|
||
# 添加数值显示标签
|
||
self.controls["raw_slider_value"] = QtWidgets.QLabel("0.000")
|
||
self.controls["raw_slider_value"].setObjectName("rawSliderValue")
|
||
self.controls["raw_slider_value"].setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||
self.controls["raw_slider_value"].setFixedWidth(40)
|
||
|
||
# 添加"All"勾选框和标签
|
||
self.controls["raw_slider_all_check"] = QtWidgets.QCheckBox("All")
|
||
self.controls["raw_slider_all_check"].setObjectName("rawSliderAllCheck")
|
||
|
||
# 页码按钮
|
||
self.buttons["page_all"] = QtWidgets.QPushButton("All")
|
||
self.buttons["page_all"].setObjectName("pageAllButton")
|
||
self.buttons["page_all"].setCheckable(True)
|
||
self.buttons["page_all"].setChecked(True)
|
||
|
||
self.buttons["page_2"] = QtWidgets.QPushButton("2")
|
||
self.buttons["page_2"].setObjectName("page2Button")
|
||
self.buttons["page_2"].setCheckable(True)
|
||
|
||
self.buttons["page_3"] = QtWidgets.QPushButton("3")
|
||
self.buttons["page_3"].setObjectName("page3Button")
|
||
self.buttons["page_3"].setCheckable(True)
|
||
|
||
self.buttons["page_4"] = QtWidgets.QPushButton("4")
|
||
self.buttons["page_4"].setObjectName("page4Button")
|
||
self.buttons["page_4"].setCheckable(True)
|
||
|
||
self.buttons["page_5"] = QtWidgets.QPushButton("5")
|
||
self.buttons["page_5"].setObjectName("page5Button")
|
||
self.buttons["page_5"].setCheckable(True)
|
||
|
||
self.buttons["page_6"] = QtWidgets.QPushButton("6")
|
||
self.buttons["page_6"].setObjectName("page6Button")
|
||
self.buttons["page_6"].setCheckable(True)
|
||
|
||
# 左下角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(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(TEXT("Raw Control", "原始控制"))
|
||
self.controls["raw_control_group"].setObjectName("rawControlGroup")
|
||
self.controls["raw_control_group"].setTitle(TEXT("Raw Control", "原始控制"))
|
||
self.controls["raw_control_group"].setFixedHeight(25)
|
||
|
||
# 右侧面板控件 - Related BlendShapes
|
||
self.controls["blendshapes_group"] = QtWidgets.QGroupBox(TEXT("Related BlendShapes", "相关BlendShapes"))
|
||
self.controls["blendshapes_group"].setObjectName("blendshapesGroup")
|
||
self.controls["blendshapes_group"].setTitle(TEXT("Related BlendShapes", "相关BlendShapes"))
|
||
self.controls["blendshapes_group"].setFixedHeight(25)
|
||
|
||
# BlendShapes列表
|
||
self.controls["blendshapes_list"] = QtWidgets.QListWidget()
|
||
self.controls["blendshapes_list"].setObjectName("blendshapesList")
|
||
self.controls["blendshapes_list"].setMinimumHeight(100)
|
||
|
||
# 底部BS滑块
|
||
self.controls["bs_slider"] = QtWidgets.QSlider(QtCore.Qt.Horizontal)
|
||
self.controls["bs_slider"].setObjectName("bsSlider")
|
||
self.controls["bs_slider"].setMinimum(0)
|
||
self.controls["bs_slider"].setMaximum(100)
|
||
self.controls["bs_slider"].setValue(0)
|
||
|
||
# 添加BS数值显示标签
|
||
self.controls["bs_slider_value"] = QtWidgets.QLabel("0.000")
|
||
self.controls["bs_slider_value"].setObjectName("bsSliderValue")
|
||
self.controls["bs_slider_value"].setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||
self.controls["bs_slider_value"].setFixedWidth(40)
|
||
|
||
# 添加BS "All"勾选框和标签
|
||
self.controls["bs_slider_all_check"] = QtWidgets.QCheckBox("All")
|
||
self.controls["bs_slider_all_check"].setObjectName("bsSliderAllCheck")
|
||
|
||
# 右下角BS 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(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(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(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(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(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(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(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(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(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(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(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(TEXT("Blend Select", "混合选择"))
|
||
self.buttons["blend_select"].setObjectName("blendSelectButton")
|
||
self.buttons["blend_select"].setIcon(ui_utils.load_icon("loading.png"))
|
||
|
||
# 创建底部主滑块
|
||
self.controls["bottom_main_slider"] = QtWidgets.QSlider(QtCore.Qt.Horizontal)
|
||
self.controls["bottom_main_slider"].setObjectName("bottomMainSlider")
|
||
self.controls["bottom_main_slider"].setMinimum(0)
|
||
self.controls["bottom_main_slider"].setMaximum(100)
|
||
self.controls["bottom_main_slider"].setValue(0)
|
||
|
||
# 添加底部主滑块数值显示标签 - 修改命名以匹配功能代码
|
||
self.controls["bottom_slider_value"] = QtWidgets.QLabel("0.000")
|
||
self.controls["bottom_slider_value"].setObjectName("bottomSliderValue")
|
||
self.controls["bottom_slider_value"].setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||
self.controls["bottom_slider_value"].setFixedWidth(40)
|
||
|
||
# 添加底部主滑块"All"勾选框 - 修改命名以匹配功能代码
|
||
self.controls["bottom_slider_all_check"] = QtWidgets.QCheckBox("All")
|
||
self.controls["bottom_slider_all_check"].setObjectName("bottomSliderAllCheck")
|
||
|
||
# 底部标签页按钮
|
||
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(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(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(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(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(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(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(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(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(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(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(TEXT("Find Mirror", "查找镜像"))
|
||
self.buttons["write_find_mirror"].setIcon(ui_utils.load_icon("mirror.png"))
|
||
self.buttons["write_find_mirror"].setObjectName("writeFindMirrorButton")
|
||
|
||
# 设置所有按钮的最小宽度为0
|
||
for button_name in ["flip_target", "mirror_target", "find_flip_target",
|
||
"add_blendshape", "delete_blendshape", "batch_blendshape",
|
||
"rebuild_select", "reposition_joints", "blend_select",
|
||
"range_minus", "range_plus", "bs_range_minus", "bs_range_plus",
|
||
"page_all", "page_2", "page_3", "page_4", "page_5", "page_6"]:
|
||
if button_name in self.buttons:
|
||
self.buttons[button_name].setMinimumWidth(0)
|
||
|
||
#========================================= LAYOUT =======================================
|
||
def create_layouts(self):
|
||
"""
|
||
创建行为系统UI布局
|
||
包括主布局、左右面板布局、滑块布局等
|
||
"""
|
||
# 创建主布局
|
||
self.layouts["main_layout"] = QtWidgets.QVBoxLayout(self.main_widget)
|
||
self.layouts["main_layout"].setContentsMargins(2, 2, 2, 2) # 减小边距
|
||
self.layouts["main_layout"].setSpacing(2) # 减小间距
|
||
|
||
# 添加标题标签到主布局
|
||
self.layouts["main_layout"].addWidget(self.controls["title_label"])
|
||
|
||
# 添加主分割器到主布局 - 设置伸缩因子为1,使其占据所有可用空间
|
||
self.layouts["main_layout"].addWidget(self.splitters["main_splitter"], 1)
|
||
|
||
# 创建左侧面板布局
|
||
self.layouts["left_layout"] = QtWidgets.QVBoxLayout(self.controls["left_panel"])
|
||
self.layouts["left_layout"].setContentsMargins(2, 2, 2, 2) # 减小边距
|
||
self.layouts["left_layout"].setSpacing(2) # 减小间距
|
||
|
||
# 创建右侧面板布局
|
||
self.layouts["right_layout"] = QtWidgets.QVBoxLayout(self.controls["right_panel"])
|
||
self.layouts["right_layout"].setContentsMargins(2, 2, 2, 2) # 减小边距
|
||
self.layouts["right_layout"].setSpacing(2) # 减小间距
|
||
|
||
# 创建左侧面板内容布局 - 不使用GroupBox,直接使用垂直布局
|
||
self.layouts["left_content_layout"] = QtWidgets.QVBoxLayout()
|
||
self.layouts["left_content_layout"].setContentsMargins(0, 0, 0, 0)
|
||
self.layouts["left_content_layout"].setSpacing(5)
|
||
|
||
# 添加标题标签
|
||
left_title = QtWidgets.QLabel(TEXT("Raw Control", "原始控制"))
|
||
left_title.setStyleSheet("font-weight: bold;")
|
||
self.layouts["left_content_layout"].addWidget(left_title)
|
||
|
||
# 添加搜索框
|
||
self.layouts["left_content_layout"].addWidget(self.controls["search_input"])
|
||
|
||
# 添加控制列表 - 设置伸缩因子为1,使其占据所有可用空间
|
||
self.layouts["left_content_layout"].addWidget(self.controls["control_list"], 1)
|
||
|
||
# 创建滑块布局
|
||
self.layouts["raw_slider_layout"] = QtWidgets.QHBoxLayout()
|
||
self.layouts["raw_slider_layout"].setContentsMargins(0, 0, 0, 0)
|
||
self.layouts["raw_slider_layout"].setSpacing(2)
|
||
self.layouts["raw_slider_layout"].addWidget(self.controls["raw_slider_value"])
|
||
self.layouts["raw_slider_layout"].addWidget(self.controls["raw_slider"])
|
||
self.layouts["raw_slider_layout"].addWidget(self.controls["raw_slider_all_check"])
|
||
|
||
# 添加滑块布局
|
||
self.layouts["left_content_layout"].addLayout(self.layouts["raw_slider_layout"])
|
||
|
||
# 范围调整按钮布局
|
||
self.layouts["range_buttons_layout"] = QtWidgets.QHBoxLayout()
|
||
self.layouts["range_buttons_layout"].setContentsMargins(0, 0, 0, 0)
|
||
self.layouts["range_buttons_layout"].setSpacing(2)
|
||
|
||
# 设置Range按钮的策略,使其均等撑满一行
|
||
size_policy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||
self.buttons["range_minus"].setSizePolicy(size_policy)
|
||
self.buttons["range_plus"].setSizePolicy(size_policy)
|
||
|
||
self.layouts["range_buttons_layout"].addWidget(self.buttons["range_minus"])
|
||
self.layouts["range_buttons_layout"].addWidget(self.buttons["range_plus"])
|
||
|
||
# 添加范围按钮布局到Raw Control布局
|
||
self.layouts["left_content_layout"].addLayout(self.layouts["range_buttons_layout"])
|
||
|
||
# 页码按钮布局
|
||
self.layouts["page_buttons_layout"] = QtWidgets.QHBoxLayout()
|
||
self.layouts["page_buttons_layout"].setContentsMargins(0, 0, 0, 0)
|
||
self.layouts["page_buttons_layout"].setSpacing(2)
|
||
|
||
# 设置页码按钮的策略,使其均等撑满一行
|
||
for button_name in [ "page_all", "page_2", "page_3", "page_4", "page_5", "page_6"]:
|
||
if button_name in self.buttons:
|
||
self.buttons[button_name].setSizePolicy(size_policy)
|
||
|
||
# 添加页码按钮到布局
|
||
for button_name in ["page_all", "page_2", "page_3", "page_4", "page_5", "page_6"]:
|
||
if button_name in self.buttons:
|
||
self.layouts["page_buttons_layout"].addWidget(self.buttons[button_name])
|
||
|
||
# 添加页码按钮布局到Raw Control布局
|
||
self.layouts["left_content_layout"].addLayout(self.layouts["page_buttons_layout"])
|
||
|
||
# 添加左侧内容布局到左侧面板布局 - 设置伸缩因子为1,使其占据所有可用空间
|
||
self.layouts["left_layout"].addLayout(self.layouts["left_content_layout"], 1)
|
||
|
||
# 创建右侧面板内容布局 - 不使用GroupBox,直接使用垂直布局
|
||
self.layouts["right_content_layout"] = QtWidgets.QVBoxLayout()
|
||
self.layouts["right_content_layout"].setContentsMargins(0, 0, 0, 0)
|
||
self.layouts["right_content_layout"].setSpacing(5)
|
||
|
||
# 添加标题标签
|
||
right_title = QtWidgets.QLabel(TEXT("Related BlendShapes", "相关BlendShapes"))
|
||
right_title.setStyleSheet("font-weight: bold;")
|
||
self.layouts["right_content_layout"].addWidget(right_title)
|
||
|
||
# 添加BlendShapes列表 - 设置伸缩因子为1,使其占据所有可用空间
|
||
self.layouts["right_content_layout"].addWidget(self.controls["blendshapes_list"], 1)
|
||
|
||
# 创建BS滑块布局,包含数值显示和滑块
|
||
self.layouts["bs_slider_layout"] = QtWidgets.QHBoxLayout()
|
||
self.layouts["bs_slider_layout"].setContentsMargins(0, 0, 0, 0)
|
||
self.layouts["bs_slider_layout"].setSpacing(2)
|
||
self.layouts["bs_slider_layout"].addWidget(self.controls["bs_slider_value"])
|
||
self.layouts["bs_slider_layout"].addWidget(self.controls["bs_slider"])
|
||
self.layouts["bs_slider_layout"].addWidget(self.controls["bs_slider_all_check"])
|
||
|
||
# 右侧滑块布局
|
||
self.layouts["right_content_layout"].addLayout(self.layouts["bs_slider_layout"])
|
||
|
||
# BS范围调整按钮布局
|
||
self.layouts["bs_range_buttons_layout"] = QtWidgets.QHBoxLayout()
|
||
self.layouts["bs_range_buttons_layout"].setContentsMargins(0, 0, 0, 0)
|
||
self.layouts["bs_range_buttons_layout"].setSpacing(2)
|
||
|
||
# 设置BS Range按钮的策略,使其均等撑满一行
|
||
self.buttons["bs_range_minus"].setSizePolicy(size_policy)
|
||
self.buttons["bs_range_plus"].setSizePolicy(size_policy)
|
||
|
||
self.layouts["bs_range_buttons_layout"].addWidget(self.buttons["bs_range_minus"])
|
||
self.layouts["bs_range_buttons_layout"].addWidget(self.buttons["bs_range_plus"])
|
||
|
||
# 添加BS范围按钮布局到BlendShapes布局
|
||
self.layouts["right_content_layout"].addLayout(self.layouts["bs_range_buttons_layout"])
|
||
|
||
# 为网格布局中的按钮设置统一策略
|
||
for button_name in ["flip_target", "mirror_target", "find_flip_target",
|
||
"add_blendshape", "delete_blendshape", "batch_blendshape",
|
||
"rebuild_select", "reposition_joints", "blend_select"]:
|
||
if button_name in self.buttons:
|
||
self.buttons[button_name].setMinimumWidth(0)
|
||
# 允许按钮缩小到极小
|
||
self.buttons[button_name].setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||
|
||
# BlendShape操作按钮网格
|
||
self.layouts["bs_buttons_grid"] = QtWidgets.QGridLayout()
|
||
self.layouts["bs_buttons_grid"].setContentsMargins(0, 0, 0, 0)
|
||
self.layouts["bs_buttons_grid"].setSpacing(2)
|
||
|
||
# 添加按钮到网格
|
||
self.layouts["bs_buttons_grid"].addWidget(self.buttons["flip_target"], 0, 0)
|
||
self.layouts["bs_buttons_grid"].addWidget(self.buttons["mirror_target"], 0, 1)
|
||
self.layouts["bs_buttons_grid"].addWidget(self.buttons["find_flip_target"], 0, 2)
|
||
self.layouts["bs_buttons_grid"].addWidget(self.buttons["add_blendshape"], 1, 0)
|
||
self.layouts["bs_buttons_grid"].addWidget(self.buttons["delete_blendshape"], 1, 1)
|
||
self.layouts["bs_buttons_grid"].addWidget(self.buttons["batch_blendshape"], 1, 2)
|
||
self.layouts["bs_buttons_grid"].addWidget(self.buttons["rebuild_select"], 2, 0)
|
||
self.layouts["bs_buttons_grid"].addWidget(self.buttons["reposition_joints"], 2, 1)
|
||
self.layouts["bs_buttons_grid"].addWidget(self.buttons["blend_select"], 2, 2)
|
||
|
||
# 添加按钮网格到BlendShapes布局
|
||
self.layouts["right_content_layout"].addLayout(self.layouts["bs_buttons_grid"])
|
||
|
||
# 添加右侧内容布局到右侧面板布局 - 设置伸缩因子为1,使其占据所有可用空间
|
||
self.layouts["right_layout"].addLayout(self.layouts["right_content_layout"], 1)
|
||
|
||
# 底部标签页按钮行
|
||
self.layouts["tab_buttons_layout"] = QtWidgets.QHBoxLayout()
|
||
self.layouts["tab_buttons_layout"].setContentsMargins(0, 0, 0, 0)
|
||
self.layouts["tab_buttons_layout"].setSpacing(0)
|
||
|
||
# 设置标签页按钮的策略,使其均等撑满一行
|
||
for button_name in ["tab_psd", "tab_bse", "tab_key", "tab_mir", "tab_ark", "tab_ctr"]:
|
||
if button_name in self.buttons:
|
||
self.buttons[button_name].setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||
self.layouts["tab_buttons_layout"].addWidget(self.buttons[button_name])
|
||
|
||
# 添加标签页按钮行到主布局
|
||
self.layouts["main_layout"].addLayout(self.layouts["tab_buttons_layout"])
|
||
|
||
# 底部按钮布局
|
||
self.layouts["bottom_buttons_layout"] = QtWidgets.QVBoxLayout()
|
||
self.layouts["bottom_buttons_layout"].setContentsMargins(0, 0, 0, 0)
|
||
self.layouts["bottom_buttons_layout"].setSpacing(5)
|
||
|
||
# 第一行按钮
|
||
self.layouts["bottom_buttons_row1"] = QtWidgets.QHBoxLayout()
|
||
self.layouts["bottom_buttons_row1"].setContentsMargins(0, 0, 0, 0)
|
||
self.layouts["bottom_buttons_row1"].setSpacing(5)
|
||
|
||
self.layouts["bottom_buttons_row1"].addWidget(self.buttons["reset_default_expression"])
|
||
self.layouts["bottom_buttons_row1"].addWidget(self.buttons["find_select_expression"])
|
||
self.layouts["bottom_buttons_row1"].addWidget(self.buttons["write_current_expressions"])
|
||
|
||
# 第二行按钮
|
||
self.layouts["bottom_buttons_row2"] = QtWidgets.QHBoxLayout()
|
||
self.layouts["bottom_buttons_row2"].setContentsMargins(0, 0, 0, 0)
|
||
self.layouts["bottom_buttons_row2"].setSpacing(5)
|
||
|
||
self.layouts["bottom_buttons_row2"].addWidget(self.buttons["controller_find"])
|
||
self.layouts["bottom_buttons_row2"].addWidget(self.buttons["select_associated_joint"])
|
||
self.layouts["bottom_buttons_row2"].addWidget(self.buttons["write_find_mirror"])
|
||
|
||
# 将两行按钮添加到底部按钮布局
|
||
self.layouts["bottom_buttons_layout"].addLayout(self.layouts["bottom_buttons_row1"])
|
||
self.layouts["bottom_buttons_layout"].addLayout(self.layouts["bottom_buttons_row2"])
|
||
|
||
# 添加底部主滑块
|
||
self.layouts["bottom_main_slider_layout"] = QtWidgets.QHBoxLayout()
|
||
self.layouts["bottom_main_slider_layout"].setContentsMargins(5, 5, 5, 5)
|
||
self.layouts["bottom_main_slider_layout"].setSpacing(5)
|
||
self.layouts["bottom_main_slider_layout"].addWidget(self.controls["bottom_slider_value"])
|
||
self.layouts["bottom_main_slider_layout"].addWidget(self.controls["bottom_main_slider"])
|
||
self.layouts["bottom_main_slider_layout"].addWidget(self.controls["bottom_slider_all_check"])
|
||
|
||
# 添加底部按钮布局和主滑块到主布局
|
||
self.layouts["main_layout"].addLayout(self.layouts["bottom_buttons_layout"])
|
||
self.layouts["main_layout"].addLayout(self.layouts["bottom_main_slider_layout"])
|
||
|
||
# 将面板添加到分割器
|
||
self.splitters["main_splitter"].addWidget(self.controls["left_panel"])
|
||
self.splitters["main_splitter"].addWidget(self.controls["right_panel"])
|
||
|
||
# 改变分割器处理大小变化的方式
|
||
self.splitters["main_splitter"].setStretchFactor(0, 1)
|
||
self.splitters["main_splitter"].setStretchFactor(1, 1)
|
||
|
||
# 在最后设置分割器比例
|
||
QtCore.QTimer.singleShot(100, lambda: ui_utils.set_splitter_proportions(self.splitters["main_splitter"], [0.5, 0.5]))
|
||
|
||
# 设置网格布局特性
|
||
self.layouts["bs_buttons_grid"].setHorizontalSpacing(1)
|
||
self.layouts["bs_buttons_grid"].setVerticalSpacing(1)
|
||
self.layouts["bs_buttons_grid"].setColumnMinimumWidth(0, 0)
|
||
self.layouts["bs_buttons_grid"].setColumnMinimumWidth(1, 0)
|
||
self.layouts["bs_buttons_grid"].setColumnMinimumWidth(2, 0)
|
||
self.layouts["bs_buttons_grid"].setColumnStretch(0, 1)
|
||
self.layouts["bs_buttons_grid"].setColumnStretch(1, 1)
|
||
self.layouts["bs_buttons_grid"].setColumnStretch(2, 1)
|
||
|
||
def create_connections(self):
|
||
"""
|
||
创建信号连接
|
||
连接按钮点击事件和其他UI事件
|
||
"""
|
||
# 底部标签页按钮连接
|
||
self.buttons["tab_psd"].clicked.connect(lambda: utils_behaviour.switch_tab(0))
|
||
self.buttons["tab_bse"].clicked.connect(lambda: utils_behaviour.switch_tab(1))
|
||
self.buttons["tab_key"].clicked.connect(lambda: utils_behaviour.switch_tab(2))
|
||
self.buttons["tab_mir"].clicked.connect(lambda: utils_behaviour.switch_tab(3))
|
||
self.buttons["tab_ark"].clicked.connect(lambda: utils_behaviour.switch_tab(4))
|
||
self.buttons["tab_ctr"].clicked.connect(lambda: utils_behaviour.switch_tab(5))
|
||
|
||
# 功能按钮连接
|
||
self.buttons["flip_target"].clicked.connect(utils_behaviour.flip_target)
|
||
self.buttons["mirror_target"].clicked.connect(utils_behaviour.mirror_target)
|
||
self.buttons["find_flip_target"].clicked.connect(utils_behaviour.find_flip_target)
|
||
self.buttons["add_blendshape"].clicked.connect(utils_behaviour.add_blendshape)
|
||
self.buttons["delete_blendshape"].clicked.connect(utils_behaviour.delete_blendshape)
|
||
self.buttons["batch_blendshape"].clicked.connect(utils_behaviour.batch_blendshape)
|
||
self.buttons["rebuild_select"].clicked.connect(utils_behaviour.rebuild_select)
|
||
self.buttons["reposition_joints"].clicked.connect(utils_behaviour.reposition_joints)
|
||
self.buttons["blend_select"].clicked.connect(utils_behaviour.blend_select)
|
||
|
||
# 表情控制按钮连接
|
||
self.buttons["reset_default_expression"].clicked.connect(utils_behaviour.reset_default_expression)
|
||
self.buttons["find_select_expression"].clicked.connect(utils_behaviour.find_select_expression)
|
||
self.buttons["write_current_expressions"].clicked.connect(utils_behaviour.write_current_expressions)
|
||
self.buttons["controller_find"].clicked.connect(utils_behaviour.controller_find)
|
||
self.buttons["select_associated_joint"].clicked.connect(utils_behaviour.select_associated_joint)
|
||
self.buttons["write_find_mirror"].clicked.connect(utils_behaviour.write_find_mirror)
|
||
|
||
# 范围按钮连接
|
||
self.buttons["range_plus"].clicked.connect(lambda: utils_behaviour.adjust_range(0.1))
|
||
self.buttons["range_minus"].clicked.connect(lambda: utils_behaviour.adjust_range(-0.1))
|
||
self.buttons["bs_range_plus"].clicked.connect(lambda: utils_behaviour.adjust_bs_range(0.1))
|
||
self.buttons["bs_range_minus"].clicked.connect(lambda: utils_behaviour.adjust_bs_range(-0.1))
|
||
|
||
# 滑块控件连接
|
||
self.controls["raw_slider"].valueChanged.connect(utils_behaviour.on_raw_slider_changed)
|
||
self.controls["bs_slider"].valueChanged.connect(utils_behaviour.on_bs_slider_changed)
|
||
self.controls["bottom_main_slider"].valueChanged.connect(utils_behaviour.on_bottom_slider_changed)
|
||
|
||
# 列表控件连接
|
||
self.controls["control_list"].itemSelectionChanged.connect(utils_behaviour.on_control_selection_changed)
|
||
self.controls["blendshapes_list"].itemSelectionChanged.connect(utils_behaviour.on_blendshape_selection_changed)
|
||
|
||
# 连接Maya选择变化事件
|
||
ui_utils.connect_maya_selection_changed(self, lambda: utils_behaviour.on_selection_changed(self), self.main_widget) |