371 lines
14 KiB
Python
371 lines
14 KiB
Python
#!/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
|
||
|
||
try:
|
||
from PySide2 import QtCore, QtGui, QtWidgets
|
||
from shiboken2 import wrapInstance
|
||
print("从PySide2加载Qt和shiboken2")
|
||
except ImportError:
|
||
try:
|
||
from PySide6 import QtCore, QtGui, QtWidgets
|
||
from shiboken6 import wrapInstance
|
||
print("从PySide6加载Qt和shiboken6")
|
||
except ImportError:
|
||
try:
|
||
from PySide import QtCore, QtGui, QtWidgets
|
||
from shiboken import wrapInstance
|
||
print("从PySide加载Qt和shiboken")
|
||
except ImportError as e:
|
||
print(f"Qt加载失败: {str(e)}")
|
||
QtCore = QtGui = QtWidgets = None
|
||
wrapInstance = None
|
||
|
||
class RiggingTab(QtWidgets.QWidget):
|
||
def __init__(self, parent=None):
|
||
super(RiggingTab, self).__init__(parent)
|
||
self._setup_ui()
|
||
self._create_connections()
|
||
|
||
def _setup_ui(self):
|
||
"""设置UI布局"""
|
||
# === Main Layout ===
|
||
self.main_layout = QtWidgets.QVBoxLayout(self)
|
||
self.main_layout.setContentsMargins(0, 0, 0, 0)
|
||
self.main_layout.setSpacing(0)
|
||
|
||
# === DNA预览区域 ===
|
||
self.preview_area = self._create_preview_area()
|
||
|
||
# === 设置区域 ===
|
||
self.settings_area = QtWidgets.QWidget()
|
||
settings_layout = QtWidgets.QVBoxLayout(self.settings_area)
|
||
settings_layout.setContentsMargins(8, 8, 8, 8)
|
||
settings_layout.setSpacing(4)
|
||
|
||
# === 资产设置 ===
|
||
asset_group = QtWidgets.QWidget()
|
||
asset_layout = QtWidgets.QGridLayout(asset_group)
|
||
asset_layout.setContentsMargins(0, 0, 0, 0)
|
||
asset_layout.setSpacing(4)
|
||
|
||
# 项目路径
|
||
path_label = QtWidgets.QLabel("项目路径:")
|
||
self.path_edit = QtWidgets.QLineEdit()
|
||
self.path_edit.setText("D:/Personal/Document/maya/SuperRiggingEditor/files/data/MetaHuman")
|
||
self.path_btn = QtWidgets.QPushButton("加载...")
|
||
self.path_btn.setIcon(QtGui.QIcon(":fileOpen.png")) # 使用Maya内置图标
|
||
self.path_btn.setFixedWidth(60) # 调整按钮宽度
|
||
self.path_btn.setFixedHeight(24)
|
||
|
||
# 预设文件
|
||
preset_label = QtWidgets.QLabel("预设文件:")
|
||
self.preset_edit = QtWidgets.QLineEdit()
|
||
self.preset_edit.setText("nal/Document/maya/SuperRiggingEditor/files/presets/metahuman/MH_Ada.dna")
|
||
self.preset_btn = QtWidgets.QPushButton("加载...")
|
||
self.preset_btn.setIcon(QtGui.QIcon(":fileOpen.png")) # 使用Maya内置图标
|
||
self.preset_btn.setFixedWidth(60) # 调整按钮宽度
|
||
self.preset_btn.setFixedHeight(24)
|
||
|
||
# 数据分层
|
||
layer_label = QtWidgets.QLabel("数据分层:")
|
||
self.layer_combo = QtWidgets.QComboBox()
|
||
self.layer_combo.addItem("行为(包括基础定义)")
|
||
self.override_check = QtWidgets.QCheckBox("覆盖表情")
|
||
self.override_check.setChecked(True)
|
||
self.override_check.setStyleSheet("""
|
||
QCheckBox {
|
||
background: transparent;
|
||
}
|
||
QCheckBox::indicator {
|
||
width: 16px;
|
||
height: 16px;
|
||
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);
|
||
}
|
||
QCheckBox::indicator:hover {
|
||
border: 1px solid #666666;
|
||
}
|
||
""")
|
||
|
||
# 添加到资产布局
|
||
asset_layout.addWidget(path_label, 0, 0)
|
||
asset_layout.addWidget(self.path_edit, 0, 1)
|
||
asset_layout.addWidget(self.path_btn, 0, 2)
|
||
asset_layout.addWidget(preset_label, 1, 0)
|
||
asset_layout.addWidget(self.preset_edit, 1, 1)
|
||
asset_layout.addWidget(self.preset_btn, 1, 2)
|
||
asset_layout.addWidget(layer_label, 2, 0)
|
||
asset_layout.addWidget(self.layer_combo, 2, 1)
|
||
asset_layout.addWidget(self.override_check, 2, 2)
|
||
|
||
# === 描述设置 ===
|
||
desc_group = QtWidgets.QWidget()
|
||
desc_layout = QtWidgets.QGridLayout(desc_group)
|
||
desc_layout.setContentsMargins(0, 0, 0, 0)
|
||
desc_layout.setSpacing(4)
|
||
|
||
# 设置列的拉伸因子,使左右两侧均等
|
||
desc_layout.setColumnStretch(0, 0) # 左侧标签不拉伸
|
||
desc_layout.setColumnStretch(1, 1) # 左侧控件拉伸
|
||
desc_layout.setColumnStretch(2, 0) # 右侧标签不拉伸
|
||
desc_layout.setColumnStretch(3, 1) # 右侧控件拉伸
|
||
|
||
# 左侧设置
|
||
left_settings = [
|
||
("名称:", "Archetype", "line"),
|
||
("原型:", "其他", "combo"),
|
||
("性别:", "女性", "combo"),
|
||
("年龄:", "24", "spin")
|
||
]
|
||
|
||
# 右侧设置
|
||
right_settings = [
|
||
("变换单位:", "厘米", "combo"),
|
||
("旋转单位:", "角度", "combo"),
|
||
("向上轴:", "Z轴向上", "combo"),
|
||
("LOD计数:", "8", "spin")
|
||
]
|
||
|
||
# 添加左侧设置
|
||
for row, (label_text, default_value, control_type) in enumerate(left_settings):
|
||
label = QtWidgets.QLabel(label_text)
|
||
label.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) # 标签左对齐
|
||
label.setFixedWidth(50) # 固定标签宽度
|
||
|
||
if control_type == "line":
|
||
control = QtWidgets.QLineEdit(default_value)
|
||
elif control_type == "combo":
|
||
control = QtWidgets.QComboBox()
|
||
control.addItem(default_value)
|
||
elif control_type == "spin":
|
||
control = QtWidgets.QSpinBox()
|
||
control.setValue(int(default_value))
|
||
|
||
desc_layout.addWidget(label, row, 0)
|
||
desc_layout.addWidget(control, row, 1)
|
||
|
||
# 添加右侧设置
|
||
for row, (label_text, default_value, control_type) in enumerate(right_settings):
|
||
label = QtWidgets.QLabel(label_text)
|
||
label.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) # 标签左对齐
|
||
label.setFixedWidth(70) # 固定标签宽度,右侧标签略宽
|
||
|
||
if control_type == "line":
|
||
control = QtWidgets.QLineEdit(default_value)
|
||
elif control_type == "combo":
|
||
control = QtWidgets.QComboBox()
|
||
control.addItem(default_value)
|
||
elif control_type == "spin":
|
||
control = QtWidgets.QSpinBox()
|
||
control.setValue(int(default_value))
|
||
|
||
desc_layout.addWidget(label, row, 2)
|
||
desc_layout.addWidget(control, row, 3)
|
||
|
||
# 设置列间距
|
||
desc_layout.setHorizontalSpacing(8) # 增加列之间的间距
|
||
|
||
# === 底部按钮 ===
|
||
button_group = QtWidgets.QWidget()
|
||
button_layout = QtWidgets.QHBoxLayout(button_group)
|
||
button_layout.setContentsMargins(8, 4, 8, 4)
|
||
button_layout.setSpacing(4) # 减小按钮间距
|
||
|
||
# 创建功能按钮
|
||
self.clear_btn = self._create_tool_button("清空选项", "delete.png", "delete.png")
|
||
self.import_btn = self._create_tool_button("导入骨架", "HIKCharacterToolSkeleton.png", "kinJoint.png")
|
||
self.create_btn = self._create_tool_button("创建骨架", "HIKcreateControlRig.png", "kinHandle.png")
|
||
|
||
# 设置按钮的大小策略
|
||
for btn in [self.clear_btn, self.import_btn, self.create_btn]:
|
||
btn.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||
btn.setMinimumHeight(32)
|
||
button_layout.addWidget(btn)
|
||
if btn != self.create_btn:
|
||
button_layout.addSpacing(4)
|
||
|
||
# === 添加到主设置布局 ===
|
||
settings_layout.addWidget(asset_group)
|
||
settings_layout.addWidget(desc_group)
|
||
settings_layout.addStretch()
|
||
settings_layout.addWidget(button_group)
|
||
|
||
# === 添加到主布局 ===
|
||
self.main_layout.addWidget(self.preview_area, stretch=1)
|
||
self.main_layout.addWidget(self.settings_area)
|
||
|
||
# === 设置样式 ===
|
||
self._setup_style()
|
||
|
||
def _create_preview_area(self):
|
||
"""创建DNA预览区域"""
|
||
widget = QtWidgets.QWidget()
|
||
layout = QtWidgets.QVBoxLayout(widget)
|
||
layout.setContentsMargins(0, 0, 0, 0)
|
||
layout.setSpacing(0)
|
||
|
||
# 预览区域 - 单个大框
|
||
preview_widget = QtWidgets.QFrame()
|
||
preview_widget.setStyleSheet("""
|
||
QFrame {
|
||
background: #1D1D1D;
|
||
border: 1px solid #555555;
|
||
}
|
||
""")
|
||
preview_widget.setMinimumHeight(300) # 调整预览区域高度
|
||
|
||
# 底部控制区域
|
||
control_widget = QtWidgets.QWidget()
|
||
control_layout = QtWidgets.QHBoxLayout(control_widget)
|
||
control_layout.setContentsMargins(8, 4, 8, 4)
|
||
control_layout.setSpacing(8)
|
||
|
||
# 左侧数值显示和滑块
|
||
value_widget = QtWidgets.QWidget()
|
||
value_layout = QtWidgets.QHBoxLayout(value_widget)
|
||
value_layout.setContentsMargins(0, 0, 0, 0)
|
||
value_layout.setSpacing(4)
|
||
|
||
self.scale_value = QtWidgets.QLabel("90")
|
||
self.scale_value.setFixedWidth(30)
|
||
self.scale_value.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||
|
||
self.scale_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal)
|
||
self.scale_slider.setRange(0, 100)
|
||
self.scale_slider.setValue(90)
|
||
self.scale_slider.valueChanged.connect(self._on_scale_changed) # 添加滑块值变化事件
|
||
|
||
value_layout.addWidget(self.scale_value)
|
||
value_layout.addWidget(self.scale_slider)
|
||
|
||
# 右侧按钮
|
||
self.export_btn = QtWidgets.QPushButton("导出预设")
|
||
self.export_btn.setIcon(QtGui.QIcon(":save.png")) # 使用Maya内置图标
|
||
self.export_btn.setFixedHeight(24)
|
||
self.export_btn.setMinimumWidth(80) # 设置最小宽度
|
||
|
||
self.import_btn = QtWidgets.QPushButton("导入预设")
|
||
self.import_btn.setIcon(QtGui.QIcon(":fileOpen.png")) # 使用Maya内置图标
|
||
self.import_btn.setFixedHeight(24)
|
||
self.import_btn.setMinimumWidth(80) # 设置最小宽度
|
||
|
||
# 添加到控制布局
|
||
# 设置这行高度
|
||
control_layout.setContentsMargins(0, 0, 0, 0)
|
||
control_layout.setSpacing(4)
|
||
control_layout.addWidget(value_widget)
|
||
control_layout.addWidget(self.export_btn)
|
||
control_layout.addWidget(self.import_btn)
|
||
|
||
|
||
# 添加到主布局
|
||
layout.addWidget(preview_widget)
|
||
layout.addWidget(control_widget)
|
||
|
||
return widget
|
||
|
||
def _create_tool_button(self, text, icon_name, fallback_icon=None):
|
||
"""创建工具按钮"""
|
||
btn = QtWidgets.QPushButton(text)
|
||
|
||
# 尝试使用自定义图标,如果失败则使用Maya内置图标
|
||
icon_path = f"{config.ICONS_PATH}/{icon_name}"
|
||
if os.path.exists(icon_path):
|
||
btn.setIcon(QtGui.QIcon(icon_path))
|
||
elif fallback_icon:
|
||
btn.setIcon(QtGui.QIcon(f":{fallback_icon}"))
|
||
|
||
return btn
|
||
|
||
def _setup_style(self):
|
||
"""设置样式"""
|
||
self.setStyleSheet("""
|
||
QWidget {
|
||
background: #2D2D2D;
|
||
color: #CCCCCC;
|
||
}
|
||
QLabel {
|
||
background: transparent;
|
||
}
|
||
QLineEdit, QComboBox {
|
||
background: #3D3D3D;
|
||
border: 1px solid #555555;
|
||
border-radius: 2px;
|
||
padding: 4px;
|
||
color: #CCCCCC;
|
||
min-height: 22px;
|
||
}
|
||
QPushButton {
|
||
background: #3D3D3D;
|
||
border: 1px solid #555555;
|
||
border-radius: 2px;
|
||
padding: 4px 8px;
|
||
color: #CCCCCC;
|
||
}
|
||
QPushButton:hover {
|
||
background: #454545;
|
||
}
|
||
QPushButton:pressed {
|
||
background: #2A2A2A;
|
||
}
|
||
QCheckBox {
|
||
spacing: 8px;
|
||
background: transparent;
|
||
}
|
||
QCheckBox::indicator {
|
||
width: 16px;
|
||
height: 16px;
|
||
}
|
||
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: 12px;
|
||
height: 12px;
|
||
margin: -4px 0;
|
||
border-radius: 6px;
|
||
}
|
||
QSlider::handle:horizontal:hover {
|
||
background: #FFFFFF;
|
||
}
|
||
""")
|
||
|
||
def _on_scale_changed(self, value):
|
||
"""滑块值变化事件处理"""
|
||
self.scale_value.setText(str(value))
|
||
|
||
def _create_connections(self):
|
||
"""创建信号连接"""
|
||
# 滑块值变化事件
|
||
self.scale_slider.valueChanged.connect(self._on_scale_changed)
|
||
# TODO: 添加信号连接
|
||
pass
|
||
|
||
if __name__ == "__main__":
|
||
pass |