#!/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 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}") 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