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

View File

@@ -4,6 +4,7 @@
"""
Behaviour UI Module for Plugin
行为系统UI模块 - 负责显示角色行为编辑界面和基础操作
基本功能:
- Blendshape自动加载刷新筛选
- 次级Blendshape自动加载刷新筛选
@@ -11,530 +12,249 @@ Behaviour UI Module for Plugin
- Blendshape范围编辑
- Blendshape镜像
- Blendshape查找翻转目标
- Blendshape重建
- 表情控制器还原默认表情
- 查找选择表情
- 控制面板查找
- 选择关联关节
- 写入当前表情
- 写入镜像表情
"""
#===================================== IMPORT MODULES =====================================
#========================================= IMPORT =========================================
from Qt import QtWidgets, QtCore, QtGui
from Qt.QtCompat import wrapInstance
from maya import OpenMayaUI as omui
import maya.cmds as cmds
import maya.mel as mel
import maya.utils as utils
import webbrowser
import subprocess
import importlib
import traceback
import locale
import sys
import os
#===================================== IMPORT FUNCTIONS ===================================
from scripts.utils import utils_behaviour as utils_behaviour
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
#========================================= LOCATION =======================================
from scripts.ui import localization
LANG = localization.LANG
#========================================== WIDGETS ==========================================
# 全局变量存储UI控件
blendshape_tree = None
sub_blendshape_tree = None
blendshape_slider = None
blendshape_preview = None
search_input = None
weight_value = None
right_slider = None
right_value = None
restore_button = None
combo_select_button = None
single_target_button = None
combo_target_button = None
batch_target_button = None
add_target_button = None
remove_target_button = None
mirror_target_button = None
flip_target_button = None
plus_button = None
all_button = None
number_buttons_layout = None
# 全局布局变量
search_layout = None
left_bottom_buttons = None
left_slider_layout = None
left_bottom_layout = None
right_slider_layout = None
right_buttons_row1 = None
right_buttons_row2 = None
right_buttons_row3 = None
tab_buttons = None
bottom_slider_layout = None
bottom_slider = None
bottom_value = None
bottom_buttons_row1 = None
bottom_buttons_row2 = None
behaviour_buttons = {}
def set_button_icon(button, icon_name):
class BehaviourUI(ui_utils.BaseUI):
"""
设置按钮图标使用Maya默认图标
Args:
button: 要设置图标的按钮
icon_name: 图标文件名
行为系统UI类 - 负责显示角色行为编辑界面和基础操作
继承自BaseUI类实现行为系统相关的UI功能
"""
# 使用Maya内置图标
from maya import cmds
# 设置按钮图标使用Maya的图标
button.setIcon(QtGui.QIcon(":/{}".format(icon_name)))
button.setIconSize(QtCore.QSize(24, 24)) # 图标尺寸
print(f"成功设置按钮图标: {icon_name}")
# 注意:如果图标加载失败,我们会看到一个空图标,但不会引起错误
#========================================== INIT ========================================
def __init__(self):
"""
初始化行为系统UI
创建主控件和布局,并连接信号和槽
"""
super(BehaviourUI, self).__init__()
# 创建主控件
self.main_widget = QtWidgets.QWidget()
self.main_widget.setObjectName("behaviourMainWidget")
# 初始化UI
self.create_widgets()
self.create_layouts()
self.create_connections()
def widgets():
"""
创建行为系统UI控件
"""
global blendshape_tree, sub_blendshape_tree, blendshape_slider, blendshape_preview, behaviour_buttons
global search_input, weight_value, right_slider, right_value, restore_button, combo_select_button
global single_target_button, combo_target_button, batch_target_button, add_target_button
global remove_target_button, mirror_target_button, flip_target_button, plus_button, all_button
global number_buttons_layout
# 全局布局变量
global search_layout, left_bottom_buttons, left_slider_layout, left_bottom_layout
global right_slider_layout, right_buttons_row1, right_buttons_row2, right_buttons_row3
global tab_buttons, bottom_slider_layout, bottom_slider, bottom_value
global bottom_buttons_row1, bottom_buttons_row2
# 创建搜索框
search_layout = QtWidgets.QHBoxLayout()
search_icon = QtWidgets.QLabel()
search_icon.setPixmap(QtGui.QIcon(":/magnifyGlass.png").pixmap(16, 16))
search_input = QtWidgets.QLineEdit()
search_input.setPlaceholderText("搜索...")
search_input.setObjectName("SearchInput")
# 主表情控制列表
blendshape_tree = QtWidgets.QListWidget()
blendshape_tree.setObjectName("RawControlList")
blendshape_tree.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
# 相关混合变形列表
sub_blendshape_tree = QtWidgets.QListWidget()
sub_blendshape_tree.setObjectName("RelatedBlendShapesList")
sub_blendshape_tree.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
# 创建权重滑块和数值显示
blendshape_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal)
blendshape_slider.setMinimum(0)
blendshape_slider.setMaximum(1000) # 使用更精细的值对应到0-1.0
blendshape_slider.setValue(0)
blendshape_slider.setObjectName("WeightSlider")
# 权重数值显示
weight_value = QtWidgets.QLineEdit("0.000")
weight_value.setFixedWidth(50)
weight_value.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
weight_value.setObjectName("WeightValue")
# 全部按钮
all_button = QtWidgets.QPushButton("全部")
all_button.setFixedWidth(60)
all_button.setObjectName("AllButton")
# 数字按钮组
number_buttons_layout = QtWidgets.QHBoxLayout()
for i in range(1, 7): # 1-6的数字按钮
num_button = QtWidgets.QPushButton(str(i))
num_button.setFixedWidth(30)
num_button.setObjectName(f"NumButton{i}")
number_buttons_layout.addWidget(num_button)
# 创建左侧底部按钮
restore_button = QtWidgets.QPushButton("恢复表情")
set_button_icon(restore_button, "undo.png")
restore_button.setObjectName("RestoreButton")
combo_select_button = QtWidgets.QPushButton("组合选择")
set_button_icon(combo_select_button, "selectByHull.png")
combo_select_button.setObjectName("ComboSelectButton")
# 创建右侧按钮
# 第一行按钮
single_target_button = QtWidgets.QPushButton("单个目标表情")
set_button_icon(single_target_button, "blendShape.png")
single_target_button.setObjectName("SingleTargetButton")
combo_target_button = QtWidgets.QPushButton("复合目标表情")
set_button_icon(combo_target_button, "blendShapeEditor.png")
combo_target_button.setObjectName("ComboTargetButton")
batch_target_button = QtWidgets.QPushButton("批量目标表情")
set_button_icon(batch_target_button, "blendShapePanel.png")
batch_target_button.setObjectName("BatchTargetButton")
# 第二行按钮
add_target_button = QtWidgets.QPushButton("添加目标表情")
set_button_icon(add_target_button, "addClip.png")
add_target_button.setObjectName("AddTargetButton")
remove_target_button = QtWidgets.QPushButton("移除目标表情")
set_button_icon(remove_target_button, "removeClip.png")
remove_target_button.setObjectName("RemoveTargetButton")
# 第三行按钮
mirror_target_button = QtWidgets.QPushButton("镜像目标表情")
set_button_icon(mirror_target_button, "mirrorJoint.png")
mirror_target_button.setObjectName("MirrorTargetButton")
flip_target_button = QtWidgets.QPushButton("翻转目标表情")
set_button_icon(flip_target_button, "flipTriangle.png")
flip_target_button.setObjectName("FlipTargetButton")
# 右侧滑块和数值显示
right_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal)
right_slider.setMinimum(0)
right_slider.setMaximum(1000) # 使用更精细的值对应到0-1.0
right_slider.setValue(0)
right_slider.setObjectName("RightSlider")
right_value = QtWidgets.QLineEdit("0.000")
right_value.setFixedWidth(50)
right_value.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
right_value.setObjectName("RightValue")
# 添加加号按钮
plus_button = QtWidgets.QPushButton("+")
plus_button.setFixedSize(30, 30)
plus_button.setObjectName("PlusButton")
# 底部按钮
# 第一行按钮
behaviour_buttons["reset_controller"] = QtWidgets.QPushButton("还原默认表情")
set_button_icon(behaviour_buttons["reset_controller"], "undo.png")
behaviour_buttons["find_expression"] = QtWidgets.QPushButton("查找选择表情")
set_button_icon(behaviour_buttons["find_expression"], "find.png")
behaviour_buttons["find_control_panel"] = QtWidgets.QPushButton("控制面板查找")
set_button_icon(behaviour_buttons["find_control_panel"], "menuIconWindow.png")
# 第二行按钮
behaviour_buttons["select_related_joints"] = QtWidgets.QPushButton("选择关联关节")
set_button_icon(behaviour_buttons["select_related_joints"], "kinJoint.png")
behaviour_buttons["write_current_expression"] = QtWidgets.QPushButton("写入当前表情")
set_button_icon(behaviour_buttons["write_current_expression"], "positionConstraint.png")
behaviour_buttons["write_mirror_expression"] = QtWidgets.QPushButton("写入镜像表情")
set_button_icon(behaviour_buttons["write_mirror_expression"], "mirrorJoint.png")
# 设置所有按钮的样式
for key, button in behaviour_buttons.items():
button.setMinimumHeight(28)
button.setStyleSheet("text-align: left; padding-left: 30px;")
button.setToolTip(button.text())
#========================================= WIDGET =======================================
def create_widgets(self):
"""
创建行为系统UI控件
包括按钮、标签、列表等
"""
# 标题标签
self.controls["title_label"] = QtWidgets.QLabel(LANG.get("behaviour_title", "角色行为"))
self.controls["title_label"].setObjectName("behaviourTitleLabel")
self.controls["title_label"].setAlignment(QtCore.Qt.AlignCenter)
# 创建主分割器
self.splitters["main_splitter"] = QtWidgets.QSplitter(QtCore.Qt.Horizontal)
self.splitters["main_splitter"].setObjectName("behaviourMainSplitter")
# 左侧面板
self.controls["left_panel"] = QtWidgets.QWidget()
self.controls["left_panel"].setObjectName("behaviourLeftPanel")
# 右侧面板
self.controls["right_panel"] = QtWidgets.QWidget()
self.controls["right_panel"].setObjectName("behaviourRightPanel")
# 左侧面板控件
# Blendshape列表
self.controls["blendshape_group"] = QtWidgets.QGroupBox(LANG.get("blendshape_group", "Blendshape列表"))
self.controls["blendshape_group"].setObjectName("blendshapeGroup")
# Blendshape列表
self.controls["blendshape_list"] = QtWidgets.QListWidget()
self.controls["blendshape_list"].setObjectName("blendshapeList")
# Blendshape刷新按钮
self.buttons["refresh_blendshape"] = QtWidgets.QPushButton(LANG.get("refresh", "刷新"))
self.buttons["refresh_blendshape"].setObjectName("refreshBlendshapeButton")
# Blendshape过滤组
self.controls["blendshape_filter_group"] = QtWidgets.QGroupBox(LANG.get("blendshape_filter", "Blendshape过滤"))
self.controls["blendshape_filter_group"].setObjectName("blendshapeFilterGroup")
# Blendshape过滤输入框
self.controls["blendshape_filter_input"] = QtWidgets.QLineEdit()
self.controls["blendshape_filter_input"].setObjectName("blendshapeFilterInput")
self.controls["blendshape_filter_input"].setPlaceholderText(LANG.get("filter_placeholder", "输入过滤条件"))
# 次级Blendshape列表组
self.controls["secondary_blendshape_group"] = QtWidgets.QGroupBox(LANG.get("secondary_blendshape_group", "次级Blendshape"))
self.controls["secondary_blendshape_group"].setObjectName("secondaryBlendshapeGroup")
# 次级Blendshape列表
self.controls["secondary_blendshape_list"] = QtWidgets.QListWidget()
self.controls["secondary_blendshape_list"].setObjectName("secondaryBlendshapeList")
# 次级Blendshape刷新按钮
self.buttons["refresh_secondary_blendshape"] = QtWidgets.QPushButton(LANG.get("refresh", "刷新"))
self.buttons["refresh_secondary_blendshape"].setObjectName("refreshSecondaryBlendshapeButton")
# 右侧面板控件
# Blendshape操作组
self.controls["blendshape_ops_group"] = QtWidgets.QGroupBox(LANG.get("blendshape_operations", "Blendshape操作"))
self.controls["blendshape_ops_group"].setObjectName("blendshapeOpsGroup")
# Blendshape操作按钮
self.buttons["export_blendshape"] = QtWidgets.QPushButton(LANG.get("export_blendshape", "导出Blendshape"))
self.buttons["import_blendshape"] = QtWidgets.QPushButton(LANG.get("import_blendshape", "导入Blendshape"))
self.buttons["edit_range"] = QtWidgets.QPushButton(LANG.get("edit_range", "编辑范围"))
self.buttons["mirror_blendshape"] = QtWidgets.QPushButton(LANG.get("mirror_blendshape", "镜像Blendshape"))
self.buttons["find_flip_target"] = QtWidgets.QPushButton(LANG.get("find_flip_target", "查找翻转目标"))
# 表情控制组
self.controls["expression_control_group"] = QtWidgets.QGroupBox(LANG.get("expression_control", "表情控制"))
self.controls["expression_control_group"].setObjectName("expressionControlGroup")
# 表情控制按钮
self.buttons["reset_expression"] = QtWidgets.QPushButton(LANG.get("reset_expression", "还原默认表情"))
self.buttons["find_expression"] = QtWidgets.QPushButton(LANG.get("find_expression", "查找选择表情"))
self.buttons["find_control_panel"] = QtWidgets.QPushButton(LANG.get("find_control_panel", "控制面板查找"))
#========================================== LAYOUTS ==========================================
def layouts(parent_tab=None):
"""
创建行为系统UI布局
Args:
parent_tab: 父容器控件由Main.py传入
"""
# 获取父容器在Main.py中创建的behaviour_tab
if not parent_tab:
parent_tab = ui_utils.get_parent_widget("behaviour_tab")
if not parent_tab:
print("无法获取父容器,布局创建失败")
return
# 创建主布局
main_layout = parent_tab.layout()
if not main_layout:
main_layout = QtWidgets.QVBoxLayout(parent_tab)
main_layout.setContentsMargins(4, 4, 4, 4)
main_layout.setSpacing(4)
main_layout.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint) # 设置布局约束为默认,允许自适应
# 创建主分割控件
main_splitter = QtWidgets.QSplitter(QtCore.Qt.Horizontal)
# 左侧区域 - Raw Control
left_widget = QtWidgets.QWidget()
left_layout = QtWidgets.QVBoxLayout(left_widget)
left_layout.setContentsMargins(2, 2, 2, 2)
left_layout.setSpacing(2)
# 标题和搜索区域
left_header = QtWidgets.QHBoxLayout()
left_title = QtWidgets.QLabel("Raw Control [000]")
left_title.setStyleSheet("font-weight: bold;")
left_header.addWidget(left_title)
left_layout.addLayout(left_header)
# 搜索框
search_layout = QtWidgets.QHBoxLayout()
search_icon = QtWidgets.QLabel()
search_icon.setPixmap(QtGui.QIcon(":/magnifyGlass.png").pixmap(16, 16))
search_layout.addWidget(search_icon)
search_layout.addWidget(search_input)
left_layout.addLayout(search_layout)
# 主列表
left_layout.addWidget(blendshape_tree)
# 底部按钮组
left_bottom_buttons = QtWidgets.QHBoxLayout()
left_bottom_buttons.addWidget(restore_button)
left_bottom_buttons.addWidget(combo_select_button)
left_layout.addLayout(left_bottom_buttons)
# 数字按钮组
left_layout.addWidget(all_button)
left_layout.addLayout(number_buttons_layout)
# 底部滑块和数值
left_slider_layout = QtWidgets.QHBoxLayout()
left_slider_layout.addWidget(weight_value)
left_slider_layout.addWidget(blendshape_slider)
left_slider_layout.addWidget(QtWidgets.QPushButton("全部"))
left_layout.addLayout(left_slider_layout)
# 左侧底部按钮组
left_bottom_layout = QtWidgets.QHBoxLayout()
left_bottom_layout.addWidget(QtWidgets.QPushButton("定义"))
left_bottom_layout.addWidget(QtWidgets.QPushButton("范围 -"))
left_layout.addLayout(left_bottom_layout)
# 右侧区域 - Related BlendShapes
right_widget = QtWidgets.QWidget()
right_layout = QtWidgets.QVBoxLayout(right_widget)
right_layout.setContentsMargins(2, 2, 2, 2)
right_layout.setSpacing(2)
# 标题
right_header = QtWidgets.QHBoxLayout()
right_title = QtWidgets.QLabel("Related BlendShapes [000]")
right_title.setStyleSheet("font-weight: bold;")
right_header.addWidget(right_title)
right_layout.addLayout(right_header)
# 相关混合变形列表
right_layout.addWidget(sub_blendshape_tree)
# 右侧滑块和数值
right_slider_layout = QtWidgets.QHBoxLayout()
right_slider_layout.addWidget(right_value)
right_slider_layout.addWidget(right_slider)
right_slider_layout.addWidget(QtWidgets.QPushButton("全部"))
right_layout.addLayout(right_slider_layout)
# 右侧按钮组 - 第一行
right_buttons_row1 = QtWidgets.QHBoxLayout()
right_buttons_row1.addWidget(single_target_button)
right_buttons_row1.addWidget(combo_target_button)
right_buttons_row1.addWidget(batch_target_button)
right_layout.addLayout(right_buttons_row1)
# 右侧按钮组 - 第二行
right_buttons_row2 = QtWidgets.QHBoxLayout()
right_buttons_row2.addWidget(add_target_button)
right_buttons_row2.addWidget(remove_target_button)
right_layout.addLayout(right_buttons_row2)
# 右侧按钮组 - 第三行
right_buttons_row3 = QtWidgets.QHBoxLayout()
right_buttons_row3.addWidget(mirror_target_button)
right_buttons_row3.addWidget(flip_target_button)
right_layout.addLayout(right_buttons_row3)
# 添加到主分割控件
main_splitter.addWidget(left_widget)
main_splitter.addWidget(right_widget)
# 设置分割比例
main_splitter.setSizes([int(parent_tab.width() * 0.5), int(parent_tab.width() * 0.5)])
# 底部按钮组
bottom_widget = QtWidgets.QWidget()
bottom_layout = QtWidgets.QVBoxLayout(bottom_widget)
bottom_layout.setContentsMargins(4, 4, 4, 4)
bottom_layout.setSpacing(4)
# 选项卡按钮组
tab_buttons = QtWidgets.QHBoxLayout()
tab_buttons.addWidget(QtWidgets.QPushButton("BS"))
tab_buttons.addWidget(QtWidgets.QPushButton("PSD"))
tab_buttons.addWidget(QtWidgets.QPushButton("KEY"))
tab_buttons.addWidget(QtWidgets.QPushButton("JNT"))
tab_buttons.addWidget(QtWidgets.QPushButton("ARK"))
tab_buttons.addWidget(QtWidgets.QPushButton("CTR"))
bottom_layout.addLayout(tab_buttons)
# 底部滑块
bottom_slider_layout = QtWidgets.QHBoxLayout()
bottom_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal)
bottom_slider.setMinimum(0)
bottom_slider.setMaximum(1000)
bottom_slider.setValue(0)
bottom_value = QtWidgets.QLineEdit("0.000")
bottom_value.setFixedWidth(50)
bottom_value.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
bottom_slider_layout.addWidget(bottom_value)
bottom_slider_layout.addWidget(bottom_slider)
bottom_slider_layout.addWidget(plus_button)
bottom_slider_layout.addWidget(QtWidgets.QPushButton("全部"))
bottom_layout.addLayout(bottom_slider_layout)
# 底部按钮组 - 第一行
bottom_buttons_row1 = QtWidgets.QHBoxLayout()
bottom_buttons_row1.addWidget(behaviour_buttons["reset_controller"])
bottom_buttons_row1.addWidget(behaviour_buttons["find_expression"])
bottom_buttons_row1.addWidget(behaviour_buttons["write_current_expression"])
bottom_layout.addLayout(bottom_buttons_row1)
# 底部按钮组 - 第二行
bottom_buttons_row2 = QtWidgets.QHBoxLayout()
bottom_buttons_row2.addWidget(behaviour_buttons["find_control_panel"])
bottom_buttons_row2.addWidget(behaviour_buttons["select_related_joints"])
bottom_buttons_row2.addWidget(behaviour_buttons["write_mirror_expression"])
bottom_layout.addLayout(bottom_buttons_row2)
# 添加到主布局
main_layout.addWidget(main_splitter, 3) # 占据更多空间
main_layout.addWidget(bottom_widget, 1) # 占据较少空间
#========================================= LAYOUT =======================================
def create_layouts(self):
"""
创建行为系统UI布局
组织控件的排列和层次结构
"""
# 主布局
self.layouts["main_layout"] = QtWidgets.QVBoxLayout(self.main_widget)
self.layouts["main_layout"].setContentsMargins(5, 5, 5, 5)
self.layouts["main_layout"].setSpacing(5)
# 添加标题标签
self.layouts["main_layout"].addWidget(self.controls["title_label"])
# 添加主分割器
self.layouts["main_layout"].addWidget(self.splitters["main_splitter"])
# 将左右面板添加到主分割器
self.splitters["main_splitter"].addWidget(self.controls["left_panel"])
self.splitters["main_splitter"].addWidget(self.controls["right_panel"])
# 左侧面板布局
self.layouts["left_layout"] = QtWidgets.QVBoxLayout(self.controls["left_panel"])
self.layouts["left_layout"].setContentsMargins(5, 5, 5, 5)
self.layouts["left_layout"].setSpacing(5)
# Blendshape列表组布局
self.layouts["blendshape_layout"] = QtWidgets.QVBoxLayout(self.controls["blendshape_group"])
self.layouts["blendshape_layout"].addWidget(self.controls["blendshape_list"])
self.layouts["blendshape_layout"].addWidget(self.buttons["refresh_blendshape"])
# Blendshape过滤组布局
self.layouts["blendshape_filter_layout"] = QtWidgets.QVBoxLayout(self.controls["blendshape_filter_group"])
self.layouts["blendshape_filter_layout"].addWidget(self.controls["blendshape_filter_input"])
# 次级Blendshape列表组布局
self.layouts["secondary_blendshape_layout"] = QtWidgets.QVBoxLayout(self.controls["secondary_blendshape_group"])
self.layouts["secondary_blendshape_layout"].addWidget(self.controls["secondary_blendshape_list"])
self.layouts["secondary_blendshape_layout"].addWidget(self.buttons["refresh_secondary_blendshape"])
# 添加组到左侧面板布局
self.layouts["left_layout"].addWidget(self.controls["blendshape_group"])
self.layouts["left_layout"].addWidget(self.controls["blendshape_filter_group"])
self.layouts["left_layout"].addWidget(self.controls["secondary_blendshape_group"])
self.layouts["left_layout"].addStretch()
# 右侧面板布局
self.layouts["right_layout"] = QtWidgets.QVBoxLayout(self.controls["right_panel"])
self.layouts["right_layout"].setContentsMargins(5, 5, 5, 5)
self.layouts["right_layout"].setSpacing(5)
# Blendshape操作组布局
self.layouts["blendshape_ops_layout"] = QtWidgets.QVBoxLayout(self.controls["blendshape_ops_group"])
self.layouts["blendshape_ops_layout"].addWidget(self.buttons["export_blendshape"])
self.layouts["blendshape_ops_layout"].addWidget(self.buttons["import_blendshape"])
self.layouts["blendshape_ops_layout"].addWidget(self.buttons["edit_range"])
self.layouts["blendshape_ops_layout"].addWidget(self.buttons["mirror_blendshape"])
self.layouts["blendshape_ops_layout"].addWidget(self.buttons["find_flip_target"])
# 表情控制组布局
self.layouts["expression_control_layout"] = QtWidgets.QVBoxLayout(self.controls["expression_control_group"])
self.layouts["expression_control_layout"].addWidget(self.buttons["reset_expression"])
self.layouts["expression_control_layout"].addWidget(self.buttons["find_expression"])
self.layouts["expression_control_layout"].addWidget(self.buttons["find_control_panel"])
# 添加组到右侧面板布局
self.layouts["right_layout"].addWidget(self.controls["blendshape_ops_group"])
self.layouts["right_layout"].addWidget(self.controls["expression_control_group"])
self.layouts["right_layout"].addStretch()
# 创建分割器大小处理器
self.resize_handlers["main_splitter"] = ui_utils.SplitterResizeHandler(
self.main_widget, self.splitters["main_splitter"], is_horizontal=True
)
#========================================== CONNECTIONS ==========================================
def connections():
"""
连接行为系统UI信号和槽
"""
# 连接主表情控制列表选择事件
blendshape_tree.itemSelectionChanged.connect(on_blendshape_selection_changed)
sub_blendshape_tree.itemSelectionChanged.connect(on_sub_blendshape_selection_changed)
# 连接滑块值变化事件
blendshape_slider.valueChanged.connect(on_blendshape_slider_changed)
# 连接底部按钮点击事件
behaviour_buttons["reset_controller"].clicked.connect(on_reset_controller)
behaviour_buttons["find_expression"].clicked.connect(on_find_expression)
behaviour_buttons["find_control_panel"].clicked.connect(on_find_control_panel)
behaviour_buttons["select_related_joints"].clicked.connect(on_select_related_joints)
behaviour_buttons["write_current_expression"].clicked.connect(on_write_current_expression)
behaviour_buttons["write_mirror_expression"].clicked.connect(on_write_mirror_expression)
# 连接其他按钮点击事件
restore_button.clicked.connect(on_restore_expression)
combo_select_button.clicked.connect(on_combo_select)
# 连接右侧按钮点击事件
single_target_button.clicked.connect(on_single_target)
combo_target_button.clicked.connect(on_combo_target)
batch_target_button.clicked.connect(on_batch_target)
add_target_button.clicked.connect(on_add_target)
remove_target_button.clicked.connect(on_remove_target)
mirror_target_button.clicked.connect(on_mirror_target)
flip_target_button.clicked.connect(on_flip_target)
#===================================== CALLBACK FUNCTIONS ===================================
def on_blendshape_selection_changed():
"""当主表情控制列表选择变化时调用"""
print("主表情控制选择已更改")
# TODO: 实现选择变化后的逻辑
def on_sub_blendshape_selection_changed():
"""当相关混合变形列表选择变化时调用"""
print("相关混合变形选择已更改")
# TODO: 实现选择变化后的逻辑
def on_blendshape_slider_changed(value):
"""当混合变形滑块值变化时调用"""
actual_value = value / 1000.0 # 转换为0-1范围
print(f"混合变形权重已更改为: {actual_value:.3f}")
# TODO: 实现权重变化后的逻辑
def on_reset_controller():
"""还原默认表情"""
print("还原默认表情功能待实现")
# TODO: 实现还原默认表情功能
def on_find_expression():
"""查找选择表情"""
print("查找选择表情功能待实现")
# TODO: 实现查找选择表情功能
def on_find_control_panel():
"""控制面板查找"""
print("控制面板查找功能待实现")
# TODO: 实现控制面板查找功能
def on_select_related_joints():
"""选择关联关节"""
print("选择关联关节功能待实现")
# TODO: 实现选择关联关节功能
def on_write_current_expression():
"""写入当前表情"""
print("写入当前表情功能待实现")
# TODO: 实现写入当前表情功能
def on_write_mirror_expression():
"""写入镜像表情"""
print("写入镜像表情功能待实现")
# TODO: 实现写入镜像表情功能
def on_restore_expression():
"""恢复表情"""
print("恢复表情功能待实现")
# TODO: 实现恢复表情功能
def on_combo_select():
"""组合选择"""
print("组合选择功能待实现")
# TODO: 实现组合选择功能
def on_single_target():
"""单个目标表情"""
print("单个目标表情功能待实现")
# TODO: 实现单个目标表情功能
def on_combo_target():
"""复合目标表情"""
print("复合目标表情功能待实现")
# TODO: 实现复合目标表情功能
def on_batch_target():
"""批量目标表情"""
print("批量目标表情功能待实现")
# TODO: 实现批量目标表情功能
def on_add_target():
"""添加目标表情"""
print("添加目标表情功能待实现")
# TODO: 实现添加目标表情功能
def on_remove_target():
"""移除目标表情"""
print("移除目标表情功能待实现")
# TODO: 实现移除目标表情功能
def on_mirror_target():
"""镜像目标表情"""
print("镜像目标表情功能待实现")
# TODO: 实现镜像目标表情功能
def on_flip_target():
"""翻转目标表情"""
print("翻转目标表情功能待实现")
# TODO: 实现翻转目标表情功能
#===================================== PLACEHOLDER FUNCTION ===================================
def behaviour_temp_function():
return utils_behaviour.behaviour_temp_utils_function()
#======================================= CONNECTION =====================================
def create_connections(self):
"""
连接信号和槽
设置UI控件的交互行为
"""
# Blendshape列表按钮连接
self.buttons["refresh_blendshape"].clicked.connect(utils_behaviour.behaviour_temp_utils_function)
# Blendshape过滤连接
self.controls["blendshape_filter_input"].textChanged.connect(utils_behaviour.behaviour_temp_utils_function)
# 次级Blendshape按钮连接
self.buttons["refresh_secondary_blendshape"].clicked.connect(utils_behaviour.behaviour_temp_utils_function)
# Blendshape操作按钮连接
self.buttons["export_blendshape"].clicked.connect(utils_behaviour.behaviour_temp_utils_function)
self.buttons["import_blendshape"].clicked.connect(utils_behaviour.behaviour_temp_utils_function)
self.buttons["edit_range"].clicked.connect(utils_behaviour.behaviour_temp_utils_function)
self.buttons["mirror_blendshape"].clicked.connect(utils_behaviour.behaviour_temp_utils_function)
self.buttons["find_flip_target"].clicked.connect(utils_behaviour.behaviour_temp_utils_function)
# 表情控制按钮连接
self.buttons["reset_expression"].clicked.connect(utils_behaviour.behaviour_temp_utils_function)
self.buttons["find_expression"].clicked.connect(utils_behaviour.behaviour_temp_utils_function)
self.buttons["find_control_panel"].clicked.connect(utils_behaviour.behaviour_temp_utils_function)