MetaFusion/scripts/ui/behaviour.py

456 lines
16 KiB
Python
Raw Normal View History

2025-02-09 22:11:50 +08:00
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#===================================== 1. Module Imports =====================================
import maya.OpenMayaUI as omui
from scripts import config
import maya.cmds as cmds
import maya.mel as mel
import webbrowser
import sys
import os
from scripts import config
2025-02-11 00:04:32 +08:00
QtCore, QtGui, QtWidgets, wrapInstance = config.Qt()
if QtCore is None or QtGui is None or QtWidgets is None or wrapInstance is None:
print(f"Qt加载失败: {QtCore}, {QtGui}, {QtWidgets}, {wrapInstance}")
2025-02-09 22:11:50 +08:00
class BehaviourTab(QtWidgets.QWidget):
2025-02-09 23:22:48 +08:00
def __init__(self, parent=None):
super(BehaviourTab, self).__init__(parent)
self._setup_ui()
def _setup_ui(self):
"""设置UI布局"""
2025-02-10 03:57:53 +08:00
# === Main Layout ===
self.main_layout = QtWidgets.QVBoxLayout(self)
self.main_layout.setContentsMargins(4, 4, 4, 4)
self.main_layout.setSpacing(4)
2025-02-09 23:22:48 +08:00
2025-02-10 03:57:53 +08:00
# === 创建水平分割布局 ===
self.splitter = QtWidgets.QSplitter(QtCore.Qt.Horizontal)
2025-02-09 23:22:48 +08:00
2025-02-10 03:57:53 +08:00
# === Raw Control 部分 ===
raw_control = QtWidgets.QWidget()
raw_layout = QtWidgets.QVBoxLayout(raw_control)
raw_layout.setContentsMargins(4, 4, 4, 4)
raw_layout.setSpacing(4)
2025-02-09 23:22:48 +08:00
2025-02-10 03:57:53 +08:00
# 标题和按钮
title_widget = QtWidgets.QWidget()
title_layout = QtWidgets.QHBoxLayout(title_widget)
title_layout.setContentsMargins(0, 0, 0, 0)
title_layout.setSpacing(4)
2025-02-09 23:22:48 +08:00
2025-02-10 03:57:53 +08:00
title = QtWidgets.QLabel("Raw Control [814/814]")
title.setStyleSheet("color: #00A5FF;")
restore_btn = QtWidgets.QPushButton("恢复表情")
blend_btn = QtWidgets.QPushButton("混合筛选")
2025-02-09 23:22:48 +08:00
2025-02-10 03:57:53 +08:00
title_layout.addWidget(title)
title_layout.addStretch()
title_layout.addWidget(restore_btn)
title_layout.addWidget(blend_btn)
2025-02-09 23:22:48 +08:00
# 搜索框
2025-02-10 03:57:53 +08:00
search_edit = QtWidgets.QLineEdit()
search_edit.setPlaceholderText("搜索...")
2025-02-09 23:22:48 +08:00
# BlendShape列表
2025-02-10 03:57:53 +08:00
blend_list = QtWidgets.QListWidget()
blend_list.setStyleSheet("""
QListWidget {
background: #232323;
border: 1px solid #555555;
}
QListWidget::item {
color: #CCCCCC;
height: 24px;
}
QListWidget::item:selected {
background: #3D3D3D;
}
""")
# 数值控制区域
value_widget = QtWidgets.QWidget()
value_layout = QtWidgets.QHBoxLayout(value_widget)
value_layout.setContentsMargins(0, 0, 0, 0)
value_layout.setSpacing(4)
self.raw_spin = QtWidgets.QDoubleSpinBox()
self.raw_spin.setValue(0.010)
self.raw_spin.setDecimals(3)
self.raw_spin.setFixedWidth(60)
2025-02-09 23:22:48 +08:00
2025-02-10 03:57:53 +08:00
self.raw_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal)
self.raw_slider.setRange(0, 100)
self.raw_slider.setValue(10) # 初始值0.010对应10
check = QtWidgets.QCheckBox()
label = QtWidgets.QLabel("全部")
value_layout.addWidget(self.raw_spin)
value_layout.addWidget(self.raw_slider)
value_layout.addWidget(check)
value_layout.addWidget(label)
2025-02-09 23:22:48 +08:00
# 过滤按钮组
2025-02-10 03:57:53 +08:00
filter_widget = QtWidgets.QWidget()
filter_layout = QtWidgets.QHBoxLayout(filter_widget)
filter_layout.setContentsMargins(0, 0, 0, 0)
filter_layout.setSpacing(4)
2025-02-09 23:22:48 +08:00
for text in ["全部", "2", "3", "4", "5", "6"]:
btn = QtWidgets.QPushButton(text)
btn.setCheckable(True)
2025-02-10 03:57:53 +08:00
btn.setFixedHeight(24)
2025-02-09 23:22:48 +08:00
filter_layout.addWidget(btn)
2025-02-10 03:57:53 +08:00
# 范围控制按钮
range_widget = QtWidgets.QWidget()
range_layout = QtWidgets.QHBoxLayout(range_widget)
range_layout.setContentsMargins(0, 0, 0, 0)
range_layout.setSpacing(4)
2025-02-09 23:22:48 +08:00
2025-02-10 03:57:53 +08:00
range_plus = QtWidgets.QPushButton("范围+")
range_minus = QtWidgets.QPushButton("范围-")
range_layout.addWidget(range_plus)
range_layout.addWidget(range_minus)
2025-02-09 23:22:48 +08:00
2025-02-10 03:57:53 +08:00
# 添加到Raw Control布局
raw_layout.addWidget(title_widget)
raw_layout.addWidget(search_edit)
raw_layout.addWidget(blend_list)
raw_layout.addWidget(value_widget)
raw_layout.addWidget(filter_widget)
raw_layout.addWidget(range_widget)
# === Related Blend Shapes 部分 ===
related_shapes = QtWidgets.QWidget()
related_layout = QtWidgets.QVBoxLayout(related_shapes)
related_layout.setContentsMargins(4, 4, 4, 4)
related_layout.setSpacing(4)
2025-02-09 23:22:48 +08:00
# 标题
2025-02-10 03:57:53 +08:00
related_title = QtWidgets.QLabel("Related Blend Shapes [858/858]")
related_title.setStyleSheet("color: #00A5FF;")
2025-02-09 23:22:48 +08:00
# BlendShape列表
2025-02-10 03:57:53 +08:00
related_list = QtWidgets.QListWidget()
related_list.setStyleSheet("""
QListWidget {
background: #232323;
border: 1px solid #555555;
}
QListWidget::item {
color: #CCCCCC;
height: 24px;
}
QListWidget::item:selected {
background: #3D3D3D;
}
""")
# 数值控制区域
related_value_widget = QtWidgets.QWidget()
related_value_layout = QtWidgets.QHBoxLayout(related_value_widget)
related_value_layout.setContentsMargins(0, 0, 0, 0)
related_value_layout.setSpacing(4)
self.related_spin = QtWidgets.QDoubleSpinBox()
self.related_spin.setValue(0.000)
self.related_spin.setDecimals(3)
self.related_spin.setFixedWidth(60)
self.related_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal)
self.related_slider.setRange(0, 100)
self.related_slider.setValue(0)
related_check = QtWidgets.QCheckBox()
related_label = QtWidgets.QLabel("全部")
2025-02-09 23:22:48 +08:00
2025-02-10 03:57:53 +08:00
related_value_layout.addWidget(self.related_spin)
related_value_layout.addWidget(self.related_slider)
related_value_layout.addWidget(related_check)
related_value_layout.addWidget(related_label)
2025-02-09 23:22:48 +08:00
# 操作按钮组 - 第一行
2025-02-10 03:57:53 +08:00
op_widget1 = QtWidgets.QWidget()
op_layout1 = QtWidgets.QHBoxLayout(op_widget1)
op_layout1.setContentsMargins(0, 0, 0, 0)
op_layout1.setSpacing(4)
flip_btn = QtWidgets.QPushButton("翻转目标")
mirror_btn = QtWidgets.QPushButton("镜像目标")
find_flip_btn = QtWidgets.QPushButton("查找翻转目标")
op_layout1.addWidget(flip_btn)
op_layout1.addWidget(mirror_btn)
op_layout1.addWidget(find_flip_btn)
2025-02-09 23:22:48 +08:00
# 操作按钮组 - 第二行
2025-02-10 03:57:53 +08:00
op_widget2 = QtWidgets.QWidget()
op_layout2 = QtWidgets.QHBoxLayout(op_widget2)
op_layout2.setContentsMargins(0, 0, 0, 0)
op_layout2.setSpacing(4)
add_btn = QtWidgets.QPushButton("添加混合目标")
delete_btn = QtWidgets.QPushButton("删除混合目标")
batch_btn = QtWidgets.QPushButton("批量混合目标")
op_layout2.addWidget(add_btn)
op_layout2.addWidget(delete_btn)
op_layout2.addWidget(batch_btn)
# 操作按钮组 - 第三行
op_widget3 = QtWidgets.QWidget()
op_layout3 = QtWidgets.QHBoxLayout(op_widget3)
op_layout3.setContentsMargins(0, 0, 0, 0)
op_layout3.setSpacing(4)
rebuild_btn = QtWidgets.QPushButton("重建混合目标")
rebuild_all_btn = QtWidgets.QPushButton("重建所有混合目标")
op_layout3.addWidget(rebuild_btn)
op_layout3.addWidget(rebuild_all_btn)
# 添加到Related布局
related_layout.addWidget(related_title)
related_layout.addWidget(related_list)
related_layout.addWidget(related_value_widget)
related_layout.addWidget(op_widget1)
related_layout.addWidget(op_widget2)
related_layout.addWidget(op_widget3)
# === 底部功能区域 ===
self.bottom_widget = QtWidgets.QWidget()
self.bottom_layout = QtWidgets.QVBoxLayout(self.bottom_widget)
2025-02-10 04:08:00 +08:00
self.bottom_layout.setContentsMargins(4, 6, 4, 6)
self.bottom_layout.setSpacing(4)
2025-02-10 03:57:53 +08:00
# 设置底部功能区的固定高度
2025-02-10 04:08:00 +08:00
self.bottom_widget.setFixedHeight(140) # 继续增加高度
2025-02-10 03:57:53 +08:00
2025-02-10 04:08:00 +08:00
# 先创建第二行需要的控件
2025-02-10 03:57:53 +08:00
self.bottom_spin = QtWidgets.QDoubleSpinBox()
self.bottom_spin.setValue(0.000)
self.bottom_spin.setDecimals(3)
self.bottom_spin.setFixedWidth(60)
2025-02-10 04:08:00 +08:00
self.bottom_spin.setFixedHeight(24)
2025-02-10 03:57:53 +08:00
self.bottom_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal)
self.bottom_slider.setRange(0, 100)
self.bottom_slider.setValue(0)
self.bottom_slider.setFixedHeight(16)
2025-02-10 04:08:00 +08:00
self.bottom_slider.setStyleSheet("""
2025-02-10 03:57:53 +08:00
QSlider::groove:horizontal {
height: 3px;
margin: 0px;
}
QSlider::handle:horizontal {
width: 8px;
height: 8px;
margin: -3px 0;
}
2025-02-10 04:08:00 +08:00
""")
2025-02-10 03:57:53 +08:00
2025-02-10 04:08:00 +08:00
# 然后创建四行的容器
2025-02-10 03:57:53 +08:00
for i in range(1, 5):
widget_name = f'func_widget{i}'
layout_name = f'func_layout{i}'
widget = QtWidgets.QWidget()
2025-02-10 04:08:00 +08:00
widget.setFixedHeight(28) # 继续增加每行高度
2025-02-10 03:57:53 +08:00
layout = QtWidgets.QHBoxLayout(widget)
layout.setContentsMargins(0, 0, 0, 0)
2025-02-10 04:08:00 +08:00
layout.setSpacing(4)
2025-02-10 03:57:53 +08:00
setattr(self, widget_name, widget)
setattr(self, layout_name, layout)
2025-02-10 04:08:00 +08:00
# 调整按钮高度
2025-02-10 03:57:53 +08:00
for btn in self.findChildren(QtWidgets.QPushButton):
2025-02-10 04:08:00 +08:00
btn.setFixedHeight(24) # 增加按钮高度
2025-02-10 03:57:53 +08:00
# 功能按钮 - 第一行
2025-02-10 04:08:00 +08:00
for text, icon in [
("PSD", ":positionConstraint.png"),
("BSE", ":blendShape.png"),
("KEY", ":key.png"),
("MIR", ":mirrorCurve.png"),
("ARK", ":arcLengthDimension.png"),
("CTR", ":control.png")
]:
2025-02-09 23:22:48 +08:00
btn = QtWidgets.QPushButton(text)
2025-02-10 04:08:00 +08:00
btn.setIcon(QtGui.QIcon(icon))
2025-02-09 23:22:48 +08:00
btn.setFixedWidth(40)
2025-02-10 03:57:53 +08:00
self.func_layout1.addWidget(btn)
self.func_layout1.addStretch()
2025-02-09 23:22:48 +08:00
2025-02-10 03:57:53 +08:00
# 功能按钮 - 第二行(范围控制)
plus_btn = QtWidgets.QPushButton("+")
plus_btn.setFixedWidth(24)
2025-02-09 23:22:48 +08:00
2025-02-10 03:57:53 +08:00
bottom_check = QtWidgets.QCheckBox()
bottom_label = QtWidgets.QLabel("全部")
2025-02-09 23:22:48 +08:00
2025-02-10 03:57:53 +08:00
self.func_layout2.addWidget(self.bottom_spin)
self.func_layout2.addWidget(self.bottom_slider)
self.func_layout2.addWidget(plus_btn)
self.func_layout2.addWidget(bottom_check)
self.func_layout2.addWidget(bottom_label)
2025-02-09 23:22:48 +08:00
2025-02-10 04:08:00 +08:00
# 功能按钮 - 第三行
2025-02-10 03:57:53 +08:00
self.restore_default_btn = QtWidgets.QPushButton("还原默认表情")
2025-02-10 04:08:00 +08:00
self.restore_default_btn.setIcon(QtGui.QIcon(":reset.png"))
self.func_layout3.addWidget(self.restore_default_btn)
2025-02-10 03:57:53 +08:00
self.find_select_btn = QtWidgets.QPushButton("查找选择表情")
2025-02-10 04:08:00 +08:00
self.find_select_btn.setIcon(QtGui.QIcon(":find.png"))
self.func_layout3.addWidget(self.find_select_btn)
2025-02-10 03:57:53 +08:00
2025-02-10 04:08:00 +08:00
self.write_current_btn = QtWidgets.QPushButton("写入当前表情")
self.write_current_btn.setIcon(QtGui.QIcon(":save.png"))
self.func_layout3.addWidget(self.write_current_btn)
2025-02-10 03:57:53 +08:00
2025-02-10 04:08:00 +08:00
# 功能按钮 - 第四行
2025-02-10 03:57:53 +08:00
self.find_panel_btn = QtWidgets.QPushButton("控制面板查找")
2025-02-10 04:08:00 +08:00
self.find_panel_btn.setIcon(QtGui.QIcon(":menuIconWindow.png"))
self.func_layout4.addWidget(self.find_panel_btn)
2025-02-10 03:57:53 +08:00
self.select_joint_btn = QtWidgets.QPushButton("选择关联关节")
2025-02-10 04:08:00 +08:00
self.select_joint_btn.setIcon(QtGui.QIcon(":kinJoint.png"))
self.func_layout4.addWidget(self.select_joint_btn)
2025-02-10 03:57:53 +08:00
2025-02-10 04:08:00 +08:00
self.write_mirror_btn = QtWidgets.QPushButton("写入镜像表情")
self.write_mirror_btn.setIcon(QtGui.QIcon(":mirrorSkinWeight.png"))
self.func_layout4.addWidget(self.write_mirror_btn)
2025-02-10 03:57:53 +08:00
# 添加到底部布局
self.bottom_layout.addWidget(self.func_widget1)
self.bottom_layout.addWidget(self.func_widget2)
self.bottom_layout.addWidget(self.func_widget3)
self.bottom_layout.addWidget(self.func_widget4)
# 添加到分割器和主布局
self.splitter.addWidget(raw_control)
self.splitter.addWidget(related_shapes)
self.main_layout.addWidget(self.splitter)
self.main_layout.addWidget(self.bottom_widget)
# === 设置样式 ===
self._setup_style()
# 添加信号连接
self.raw_slider.valueChanged.connect(lambda v: self._on_slider_changed(self.raw_spin, v))
self.related_slider.valueChanged.connect(lambda v: self._on_slider_changed(self.related_spin, v))
self.bottom_slider.valueChanged.connect(lambda v: self._on_slider_changed(self.bottom_spin, v))
def _setup_style(self):
"""设置样式"""
self.setStyleSheet("""
QWidget {
background: #2D2D2D;
color: #CCCCCC;
}
QLabel {
background: transparent;
}
QLineEdit, QDoubleSpinBox {
background: #3D3D3D;
border: 1px solid #555555;
border-radius: 2px;
padding: 2px 4px;
min-height: 20px;
}
QPushButton {
background: #3D3D3D;
border: 1px solid #555555;
border-radius: 2px;
padding: 2px 4px;
min-height: 22px;
}
QPushButton:hover {
background: #454545;
}
QPushButton:pressed {
background: #2A2A2A;
}
QCheckBox {
spacing: 4px;
background: transparent;
}
QCheckBox::indicator {
width: 14px;
height: 14px;
background: #3D3D3D;
border: 1px solid #555555;
border-radius: 2px;
}
QCheckBox::indicator:checked {
background: #3D3D3D;
image: url(:checkboxChecked.png);
}
QCheckBox::indicator:unchecked {
background: #3D3D3D;
image: url(:checkboxUnchecked.png);
}
QSlider::groove:horizontal {
border: 1px solid #555555;
height: 4px;
background: #3D3D3D;
margin: 0px;
border-radius: 2px;
}
QSlider::handle:horizontal {
background: #CCCCCC;
border: 1px solid #555555;
width: 10px;
height: 10px;
margin: -3px 0;
border-radius: 5px;
}
QSlider::handle:horizontal:hover {
background: #FFFFFF;
}
QListWidget {
background: #232323;
border: 1px solid #555555;
}
QListWidget::item {
height: 22px;
padding: 0px 4px;
border-bottom: 1px solid #383838;
}
QListWidget::item:selected {
background: #4D4D4D;
}
QListWidget::item:hover {
background: #454545;
}
""")
# 调整分割器的初始大小比例
self.splitter.setSizes([int(self.width() * 0.45), int(self.width() * 0.55)])
# 功能按钮 - 第一行到第四行的布局
for layout in [self.func_layout1, self.func_layout2, self.func_layout3, self.func_layout4]:
layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(2) # 统一按钮间距
# 所有功能按钮widget的布局
for widget in [self.func_widget1, self.func_widget2, self.func_widget3, self.func_widget4]:
widget.setContentsMargins(0, 0, 0, 0)
2025-02-09 23:22:48 +08:00
2025-02-10 03:57:53 +08:00
def _on_slider_changed(self, spin_box, value):
"""处理滑块值变化"""
spin_box.setValue(value / 1000.0) # 将0-100的值转换为0.000-0.100
2025-02-09 22:11:50 +08:00
if __name__ == "__main__":
pass