Update
This commit is contained in:
@@ -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)
|
Reference in New Issue
Block a user