MetaFusion/scripts/ui/rigging.py
2025-02-06 19:49:53 +08:00

233 lines
9.0 KiB
Python

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#===================================== 1. Module Imports =====================================
import maya.cmds as cmds
import maya.mel as mel
import sys
import os
from scripts.config import data
from scripts.ui import rigging_utils as rigging_utils
from scripts.ui import widgets as widgets
try:
from PySide2 import QtCore, QtGui, QtWidgets
from shiboken2 import wrapInstance
except ImportError:
try:
from PySide6 import QtCore, QtGui, QtWidgets
from shiboken6 import wrapInstance
except ImportError:
try:
from PySide import QtCore, QtGui, QtWidgets
from shiboken import wrapInstance
except ImportError as e:
QtCore = QtGui = QtWidgets = None
wrapInstance = None
#===================================== 2. Rigging Tab Class =====================================
class RiggingTab(widgets.BaseWidget):
"""绑定标签页"""
def __init__(self, parent=None):
self.dna_browser = None
self.dna_flow = None # DNA按钮流布局
self.scale_slider = None
self.dna_buttons = [] # 存储DNA按钮
self.current_scale = 90 # 当前缩放值
super(RiggingTab, self).__init__(parent)
def setup_ui(self):
"""初始化UI"""
layout = QtWidgets.QVBoxLayout(self)
layout.setSpacing(self.SPACING)
layout.setContentsMargins(self.MARGINS, self.MARGINS,
self.MARGINS, self.MARGINS)
# DNA浏览器区域
browser_group = QtWidgets.QGroupBox("预览")
browser_layout = QtWidgets.QVBoxLayout()
# DNA按钮流布局
self.dna_flow = QtWidgets.QGridLayout()
self.dna_flow.setSpacing(5)
# 创建滚动区域
scroll_widget = QtWidgets.QWidget()
scroll_widget.setLayout(self.dna_flow)
scroll_area = QtWidgets.QScrollArea()
scroll_area.setWidget(scroll_widget)
scroll_area.setWidgetResizable(True)
scroll_area.setMinimumHeight(300)
scroll_area.setStyleSheet("QScrollArea { background-color: #333333; }")
browser_layout.addWidget(scroll_area)
# 缩放滑块
slider_layout = QtWidgets.QHBoxLayout()
self.scale_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal)
self.scale_slider.setRange(50, 150)
self.scale_slider.setValue(self.current_scale)
self.scale_slider.valueChanged.connect(self._on_scale_changed)
# 添加数值显示
self.scale_label = QtWidgets.QLabel(f"{self.current_scale}")
slider_layout.addWidget(self.scale_label)
slider_layout.addWidget(self.scale_slider)
# 导入导出按钮
button_layout = QtWidgets.QHBoxLayout()
button_layout.addWidget(widgets.IconButton("export.png", "导出预览"))
button_layout.addWidget(widgets.IconButton("import.png", "导入预览"))
slider_layout.addLayout(button_layout)
browser_layout.addLayout(slider_layout)
browser_group.setLayout(browser_layout)
layout.addWidget(browser_group)
# 资产设置区域
settings_layout = QtWidgets.QVBoxLayout()
# 项目路径
project_layout = QtWidgets.QHBoxLayout()
project_layout.addWidget(QtWidgets.QLabel("项目路径:"))
project_input = widgets.ModernLineEdit(read_only=True)
project_input.setText("D:/Personal/Document/maya/SuperRiggingEditor/files/data/MetaHuman")
project_layout.addWidget(project_input)
project_layout.addWidget(widgets.IconButton("folder.png", "加载..."))
settings_layout.addLayout(project_layout)
# 预设文件
preset_layout = QtWidgets.QHBoxLayout()
preset_layout.addWidget(QtWidgets.QLabel("预设文件:"))
preset_input = widgets.ModernLineEdit(read_only=True)
preset_layout.addWidget(preset_input)
preset_layout.addWidget(widgets.IconButton("folder.png", "加载..."))
settings_layout.addLayout(preset_layout)
# 数据层设置
data_layout = QtWidgets.QHBoxLayout()
data_layout.addWidget(QtWidgets.QLabel("数据层:"))
data_combo = QtWidgets.QComboBox()
data_combo.addItem("无效(未定义)")
data_layout.addWidget(data_combo)
data_layout.addWidget(QtWidgets.QCheckBox("检查清理"))
settings_layout.addLayout(data_layout)
# 描述信息
desc_group = QtWidgets.QGroupBox("描述")
desc_layout = QtWidgets.QGridLayout()
desc_fields = [
("名称:", ""),
("原型:", "亚洲人"),
("性别:", "女性"),
("年龄:", "18"),
("变换单位:", "厘米"),
("旋转单位:", "角度"),
("向上轴:", "Z轴向上"),
("LOD升级:", "0")
]
for i, (label, default) in enumerate(desc_fields):
desc_layout.addWidget(QtWidgets.QLabel(label), i, 0)
if i in [1, 2, 4, 5, 6]: # 这些字段使用下拉框
combo = QtWidgets.QComboBox()
combo.addItem(default)
desc_layout.addWidget(combo, i, 1)
else: # 其他字段使用输入框
input_widget = widgets.ModernLineEdit()
input_widget.setText(default)
desc_layout.addWidget(input_widget, i, 1)
desc_group.setLayout(desc_layout)
settings_layout.addWidget(desc_group)
# 底部按钮
bottom_layout = QtWidgets.QHBoxLayout()
btn = widgets.IconButton("clear.png", "清空预览")
btn.clicked.connect(lambda checked=False, cb=rigging_utils.clear_preview: cb())
bottom_layout.addWidget(btn)
bottom_layout.addWidget(widgets.IconButton("import.png", "导入预览"))
bottom_layout.addWidget(widgets.IconButton("create.png", "创建预览"))
settings_layout.addLayout(bottom_layout)
layout.addLayout(settings_layout)
def _on_scale_changed(self, value):
"""缩放值改变时更新按钮大小"""
self.current_scale = value
self.scale_label.setText(f"{value}")
self._update_button_size()
def _update_button_size(self):
"""更新所有DNA按钮的大小"""
size = int(self.current_scale * 1.5) # 将滑块值转换为合适的按钮大小
for btn in self.dna_buttons:
btn.setFixedSize(size, size)
def _create_dna_button(self, dna_file, img_file):
"""创建DNA按钮"""
btn = QtWidgets.QPushButton()
btn.setFixedSize(int(self.current_scale * 1.5), int(self.current_scale * 1.5))
# 设置图标
if os.path.exists(img_file):
icon = QtGui.QIcon(img_file)
else:
# 使用默认图标
default_img = os.path.join(data.DNA_IMG_PATH, "Default.png")
if os.path.exists(default_img):
icon = QtGui.QIcon(default_img)
else:
# 如果默认图标也不存在,使用系统默认图标
icon = QtGui.QIcon.fromTheme("image-missing")
btn.setIcon(icon)
btn.setIconSize(QtCore.QSize(int(self.current_scale * 1.4), int(self.current_scale * 1.4)))
# 设置工具提示为DNA文件名
btn.setToolTip(os.path.basename(dna_file))
# 点击事件
btn.clicked.connect(lambda: self._on_dna_clicked(dna_file))
return btn
def refresh_dna_browser(self):
"""刷新DNA浏览器"""
# 清除现有按钮
for btn in self.dna_buttons:
self.dna_flow.removeWidget(btn)
btn.deleteLater()
self.dna_buttons.clear()
# 获取DNA和图片文件
dna_path = data.DNA_FILE_PATH
img_path = data.DNA_IMG_PATH
if not os.path.exists(dna_path) or not os.path.exists(img_path):
return
# 加载DNA文件和对应的预览图
dna_files = [f for f in os.listdir(dna_path) if f.endswith('.dna')]
for i, dna_file in enumerate(dna_files):
base_name = os.path.splitext(dna_file)[0]
img_file = os.path.join(img_path, f"{base_name}.png")
dna_file_path = os.path.join(dna_path, dna_file)
if os.path.exists(img_file):
btn = self._create_dna_button(dna_file_path, img_file)
self.dna_buttons.append(btn)
# 添加到网格布局
row = i // 4 # 每行4个按钮
col = i % 4
self.dna_flow.addWidget(btn, row, col)
def _on_dna_clicked(self, dna_file):
"""DNA按钮点击事件"""
try:
rigging_utils.load_dna(dna_file)
except Exception as e:
cmds.warning(f"加载DNA失败: {str(e)}")