836 lines
36 KiB
Python
836 lines
36 KiB
Python
#!/usr/bin/env python
|
||
# -*- coding: utf-8 -*-
|
||
|
||
"""
|
||
Rigging UI Module for Plugin
|
||
绑定系统UI模块 - 负责显示骨骼绑定编辑界面和基础操作
|
||
基本功能:
|
||
- DNA浏览器
|
||
- 根据DNA导入骨骼
|
||
- 根据DNA生成身体
|
||
- DNA校准
|
||
- 骨骼位置校准
|
||
- 创建绑定
|
||
- 复制蒙皮
|
||
"""
|
||
#========================================= 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
|
||
from scripts.ui import ui_utils
|
||
from scripts.utils import utils_rigging
|
||
#========================================== 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
|
||
|
||
class RiggingUI(ui_utils.BaseUI):
|
||
"""
|
||
绑定系统UI类 - 负责显示骨骼绑定编辑界面和基础操作
|
||
继承自BaseUI类,实现绑定系统相关的UI功能
|
||
"""
|
||
#======================================= FUNCTIONS ======================================
|
||
def on_show_event(self, event):
|
||
"""
|
||
显示事件处理
|
||
当面板显示时重置分割器大小
|
||
"""
|
||
self.reset_splitter_sizes()
|
||
super(RiggingUI, self).showEvent(event)
|
||
|
||
def reset_splitter_sizes(self):
|
||
"""
|
||
重置分割器大小,确保左右栏宽度均等
|
||
"""
|
||
if self.splitters["main_splitter"]:
|
||
width = self.splitters["main_splitter"].width()
|
||
self.splitters["main_splitter"].setSizes([width // 2, width // 2])
|
||
|
||
def on_splitter_moved(self, pos, index):
|
||
"""
|
||
分割器移动事件处理
|
||
记录当前分割器位置
|
||
"""
|
||
utils_rigging.update_splitter_position(self.splitters["main_splitter"])
|
||
|
||
# 左侧面板 - 骨骼列表操作
|
||
def add_joint(self):
|
||
"""
|
||
添加关节
|
||
"""
|
||
utils_rigging.add_joint(self.controls["skeleton_list"])
|
||
|
||
def remove_joint(self):
|
||
"""
|
||
移除关节
|
||
"""
|
||
utils_rigging.remove_joint(self.controls["skeleton_list"])
|
||
|
||
def duplicate_joint(self):
|
||
"""
|
||
复制关节
|
||
"""
|
||
utils_rigging.duplicate_joint(self.controls["skeleton_list"])
|
||
|
||
def on_joint_selection_changed(self):
|
||
"""
|
||
关节选择变化事件
|
||
更新关节属性面板
|
||
"""
|
||
utils_rigging.update_joint_properties(
|
||
self.controls["skeleton_list"],
|
||
self.controls["joint_name_input"],
|
||
self.controls["joint_x_input"],
|
||
self.controls["joint_y_input"],
|
||
self.controls["joint_z_input"],
|
||
self.controls["joint_rx_input"],
|
||
self.controls["joint_ry_input"],
|
||
self.controls["joint_rz_input"],
|
||
self.controls["joint_sx_input"],
|
||
self.controls["joint_sy_input"],
|
||
self.controls["joint_sz_input"]
|
||
)
|
||
|
||
# 左侧面板 - 控制器列表操作
|
||
def add_controller(self):
|
||
"""
|
||
添加控制器
|
||
"""
|
||
utils_rigging.add_controller(self.controls["controller_list"])
|
||
|
||
def remove_controller(self):
|
||
"""
|
||
移除控制器
|
||
"""
|
||
utils_rigging.remove_controller(self.controls["controller_list"])
|
||
|
||
def duplicate_controller(self):
|
||
"""
|
||
复制控制器
|
||
"""
|
||
utils_rigging.duplicate_controller(self.controls["controller_list"])
|
||
|
||
def on_controller_selection_changed(self):
|
||
"""
|
||
控制器选择变化事件
|
||
更新控制器属性
|
||
"""
|
||
utils_rigging.update_controller_properties(self.controls["controller_list"])
|
||
|
||
# 右侧面板 - 关节属性
|
||
def on_joint_name_changed(self):
|
||
"""
|
||
关节名称变化事件
|
||
"""
|
||
utils_rigging.update_joint_name(
|
||
self.controls["skeleton_list"],
|
||
self.controls["joint_name_input"]
|
||
)
|
||
|
||
def on_joint_position_changed(self, axis):
|
||
"""
|
||
关节位置变化事件
|
||
"""
|
||
utils_rigging.update_joint_position(
|
||
self.controls["skeleton_list"],
|
||
axis,
|
||
self.controls[f"joint_{axis}_input"]
|
||
)
|
||
|
||
def on_joint_rotation_changed(self, axis):
|
||
"""
|
||
关节旋转变化事件
|
||
"""
|
||
utils_rigging.update_joint_rotation(
|
||
self.controls["skeleton_list"],
|
||
axis,
|
||
self.controls[f"joint_r{axis}_input"]
|
||
)
|
||
|
||
def on_joint_scale_changed(self, axis):
|
||
"""
|
||
关节缩放变化事件
|
||
"""
|
||
utils_rigging.update_joint_scale(
|
||
self.controls["skeleton_list"],
|
||
axis,
|
||
self.controls[f"joint_s{axis}_input"]
|
||
)
|
||
|
||
def apply_joint_properties(self):
|
||
"""
|
||
应用关节属性
|
||
"""
|
||
utils_rigging.apply_joint_properties(
|
||
self.controls["skeleton_list"],
|
||
self.controls["joint_name_input"],
|
||
self.controls["joint_x_input"],
|
||
self.controls["joint_y_input"],
|
||
self.controls["joint_z_input"],
|
||
self.controls["joint_rx_input"],
|
||
self.controls["joint_ry_input"],
|
||
self.controls["joint_rz_input"],
|
||
self.controls["joint_sx_input"],
|
||
self.controls["joint_sy_input"],
|
||
self.controls["joint_sz_input"]
|
||
)
|
||
|
||
def reset_joint_properties(self):
|
||
"""
|
||
重置关节属性
|
||
"""
|
||
utils_rigging.reset_joint_properties(
|
||
self.controls["skeleton_list"],
|
||
self.controls["joint_name_input"],
|
||
self.controls["joint_x_input"],
|
||
self.controls["joint_y_input"],
|
||
self.controls["joint_z_input"],
|
||
self.controls["joint_rx_input"],
|
||
self.controls["joint_ry_input"],
|
||
self.controls["joint_rz_input"],
|
||
self.controls["joint_sx_input"],
|
||
self.controls["joint_sy_input"],
|
||
self.controls["joint_sz_input"]
|
||
)
|
||
|
||
# 右侧面板 - 绑定工具
|
||
def create_binding(self):
|
||
"""
|
||
创建绑定
|
||
"""
|
||
utils_rigging.create_binding()
|
||
|
||
def copy_skin(self):
|
||
"""
|
||
复制蒙皮
|
||
"""
|
||
utils_rigging.copy_skin()
|
||
|
||
def mirror_skin(self):
|
||
"""
|
||
镜像蒙皮
|
||
"""
|
||
utils_rigging.mirror_skin()
|
||
|
||
def paint_weights(self):
|
||
"""
|
||
绘制权重
|
||
"""
|
||
utils_rigging.paint_weights()
|
||
|
||
# 底部工具面板 - DNA操作
|
||
def import_dna(self):
|
||
"""
|
||
导入DNA
|
||
"""
|
||
utils_rigging.import_dna()
|
||
|
||
def export_dna(self):
|
||
"""
|
||
导出DNA
|
||
"""
|
||
utils_rigging.export_dna()
|
||
|
||
def calibrate_dna(self):
|
||
"""
|
||
校准DNA
|
||
"""
|
||
utils_rigging.calibrate_dna()
|
||
|
||
# 底部工具面板 - 骨骼工具
|
||
def import_skeleton(self):
|
||
"""
|
||
导入骨骼
|
||
"""
|
||
utils_rigging.import_skeleton()
|
||
|
||
def export_skeleton(self):
|
||
"""
|
||
导出骨骼
|
||
"""
|
||
utils_rigging.export_skeleton()
|
||
|
||
def calibrate_skeleton(self):
|
||
"""
|
||
校准骨骼
|
||
"""
|
||
utils_rigging.calibrate_skeleton()
|
||
|
||
# 底部工具面板 - 绑定工具
|
||
def generate_controllers(self):
|
||
"""
|
||
生成控制器
|
||
"""
|
||
utils_rigging.generate_controllers()
|
||
|
||
def generate_body(self):
|
||
"""
|
||
生成身体
|
||
"""
|
||
utils_rigging.generate_body()
|
||
|
||
def clean_rigging(self):
|
||
"""
|
||
清理绑定
|
||
"""
|
||
utils_rigging.clean_rigging()
|
||
|
||
#========================================== INIT ========================================
|
||
def __init__(self):
|
||
"""
|
||
初始化绑定系统UI
|
||
创建主控件和布局,并连接信号和槽
|
||
"""
|
||
super(RiggingUI, self).__init__()
|
||
|
||
# 创建主控件
|
||
self.main_widget = QtWidgets.QWidget()
|
||
self.main_widget.setObjectName("riggingMainWidget")
|
||
|
||
# 初始化UI
|
||
self.create_widgets()
|
||
self.create_layouts()
|
||
self.create_connections()
|
||
|
||
#========================================= WIDGET =======================================
|
||
def create_widgets(self):
|
||
"""
|
||
创建绑定系统UI控件
|
||
包括按钮、标签、列表等
|
||
"""
|
||
# 标题标签 - 使用HTML格式化标题
|
||
title_text = f"<h4 style='margin:0;padding:5px;'>{LANG.get('rigging_title', '骨骼绑定')}</h4>"
|
||
self.controls["title_label"] = QtWidgets.QLabel(title_text)
|
||
self.controls["title_label"].setObjectName("riggingTitleLabel")
|
||
self.controls["title_label"].setAlignment(QtCore.Qt.AlignCenter)
|
||
self.controls["title_label"].setMaximumHeight(30) # 限制标题高度
|
||
|
||
# 左侧面板
|
||
self.controls["left_panel"] = QtWidgets.QWidget()
|
||
self.controls["left_panel"].setObjectName("riggingLeftPanel")
|
||
|
||
# 右侧面板
|
||
self.controls["right_panel"] = QtWidgets.QWidget()
|
||
self.controls["right_panel"].setObjectName("riggingRightPanel")
|
||
|
||
# 左侧面板控件 - 骨骼列表
|
||
self.controls["skeleton_group"] = QtWidgets.QGroupBox("Skeleton [000]")
|
||
self.controls["skeleton_group"].setObjectName("skeletonGroup")
|
||
|
||
# 骨骼列表
|
||
self.controls["skeleton_list"] = QtWidgets.QListWidget()
|
||
self.controls["skeleton_list"].setObjectName("skeletonList")
|
||
|
||
# 添加测试项目
|
||
for i in range(5):
|
||
item = QtWidgets.QListWidgetItem(f"Joint_{i}")
|
||
self.controls["skeleton_list"].addItem(item)
|
||
|
||
# 骨骼操作按钮
|
||
self.buttons["add_joint"] = QtWidgets.QPushButton(LANG.get("add_joint", "添加关节"))
|
||
self.buttons["add_joint"].setObjectName("addJointButton")
|
||
|
||
self.buttons["remove_joint"] = QtWidgets.QPushButton(LANG.get("remove_joint", "移除关节"))
|
||
self.buttons["remove_joint"].setObjectName("removeJointButton")
|
||
|
||
self.buttons["duplicate_joint"] = QtWidgets.QPushButton(LANG.get("duplicate_joint", "复制关节"))
|
||
self.buttons["duplicate_joint"].setObjectName("duplicateJointButton")
|
||
|
||
# 左侧面板控件 - 控制器列表
|
||
self.controls["controller_group"] = QtWidgets.QGroupBox("Controllers [000]")
|
||
self.controls["controller_group"].setObjectName("controllerGroup")
|
||
|
||
# 控制器列表
|
||
self.controls["controller_list"] = QtWidgets.QListWidget()
|
||
self.controls["controller_list"].setObjectName("controllerList")
|
||
|
||
# 添加测试项目
|
||
for i in range(3):
|
||
item = QtWidgets.QListWidgetItem(f"Controller_{i}")
|
||
self.controls["controller_list"].addItem(item)
|
||
|
||
# 控制器操作按钮
|
||
self.buttons["add_controller"] = QtWidgets.QPushButton(LANG.get("add_controller", "添加控制器"))
|
||
self.buttons["add_controller"].setObjectName("addControllerButton")
|
||
|
||
self.buttons["remove_controller"] = QtWidgets.QPushButton(LANG.get("remove_controller", "移除控制器"))
|
||
self.buttons["remove_controller"].setObjectName("removeControllerButton")
|
||
|
||
self.buttons["duplicate_controller"] = QtWidgets.QPushButton(LANG.get("duplicate_controller", "复制控制器"))
|
||
self.buttons["duplicate_controller"].setObjectName("duplicateControllerButton")
|
||
|
||
# 右侧面板控件 - 关节属性
|
||
self.controls["joint_properties_group"] = QtWidgets.QGroupBox(LANG.get("joint_properties", "关节属性"))
|
||
self.controls["joint_properties_group"].setObjectName("jointPropertiesGroup")
|
||
|
||
# 关节名称标签和输入框
|
||
self.controls["joint_name_label"] = QtWidgets.QLabel(LANG.get("name", "名称:"))
|
||
self.controls["joint_name_label"].setObjectName("jointNameLabel")
|
||
|
||
self.controls["joint_name_input"] = QtWidgets.QLineEdit()
|
||
self.controls["joint_name_input"].setObjectName("jointNameInput")
|
||
self.controls["joint_name_input"].setPlaceholderText(LANG.get("enter_joint_name", "输入关节名称"))
|
||
|
||
# 关节位置标签和输入框
|
||
self.controls["joint_position_label"] = QtWidgets.QLabel(LANG.get("position", "位置:"))
|
||
self.controls["joint_position_label"].setObjectName("jointPositionLabel")
|
||
|
||
# X坐标
|
||
self.controls["joint_x_label"] = QtWidgets.QLabel("X:")
|
||
self.controls["joint_x_label"].setObjectName("jointXLabel")
|
||
|
||
self.controls["joint_x_input"] = QtWidgets.QLineEdit("0.0")
|
||
self.controls["joint_x_input"].setObjectName("jointXInput")
|
||
|
||
# Y坐标
|
||
self.controls["joint_y_label"] = QtWidgets.QLabel("Y:")
|
||
self.controls["joint_y_label"].setObjectName("jointYLabel")
|
||
|
||
self.controls["joint_y_input"] = QtWidgets.QLineEdit("0.0")
|
||
self.controls["joint_y_input"].setObjectName("jointYInput")
|
||
|
||
# Z坐标
|
||
self.controls["joint_z_label"] = QtWidgets.QLabel("Z:")
|
||
self.controls["joint_z_label"].setObjectName("jointZLabel")
|
||
|
||
self.controls["joint_z_input"] = QtWidgets.QLineEdit("0.0")
|
||
self.controls["joint_z_input"].setObjectName("jointZInput")
|
||
|
||
# 关节旋转标签和输入框
|
||
self.controls["joint_rotation_label"] = QtWidgets.QLabel(LANG.get("rotation", "旋转:"))
|
||
self.controls["joint_rotation_label"].setObjectName("jointRotationLabel")
|
||
|
||
# X旋转
|
||
self.controls["joint_rx_label"] = QtWidgets.QLabel("X:")
|
||
self.controls["joint_rx_label"].setObjectName("jointRXLabel")
|
||
|
||
self.controls["joint_rx_input"] = QtWidgets.QLineEdit("0.0")
|
||
self.controls["joint_rx_input"].setObjectName("jointRXInput")
|
||
|
||
# Y旋转
|
||
self.controls["joint_ry_label"] = QtWidgets.QLabel("Y:")
|
||
self.controls["joint_ry_label"].setObjectName("jointRYLabel")
|
||
|
||
self.controls["joint_ry_input"] = QtWidgets.QLineEdit("0.0")
|
||
self.controls["joint_ry_input"].setObjectName("jointRYInput")
|
||
|
||
# Z旋转
|
||
self.controls["joint_rz_label"] = QtWidgets.QLabel("Z:")
|
||
self.controls["joint_rz_label"].setObjectName("jointRZLabel")
|
||
|
||
self.controls["joint_rz_input"] = QtWidgets.QLineEdit("0.0")
|
||
self.controls["joint_rz_input"].setObjectName("jointRZInput")
|
||
|
||
# 关节缩放标签和输入框
|
||
self.controls["joint_scale_label"] = QtWidgets.QLabel(LANG.get("scale", "缩放:"))
|
||
self.controls["joint_scale_label"].setObjectName("jointScaleLabel")
|
||
|
||
# X缩放
|
||
self.controls["joint_sx_label"] = QtWidgets.QLabel("X:")
|
||
self.controls["joint_sx_label"].setObjectName("jointSXLabel")
|
||
|
||
self.controls["joint_sx_input"] = QtWidgets.QLineEdit("1.0")
|
||
self.controls["joint_sx_input"].setObjectName("jointSXInput")
|
||
|
||
# Y缩放
|
||
self.controls["joint_sy_label"] = QtWidgets.QLabel("Y:")
|
||
self.controls["joint_sy_label"].setObjectName("jointSYLabel")
|
||
|
||
self.controls["joint_sy_input"] = QtWidgets.QLineEdit("1.0")
|
||
self.controls["joint_sy_input"].setObjectName("jointSYInput")
|
||
|
||
# Z缩放
|
||
self.controls["joint_sz_label"] = QtWidgets.QLabel("Z:")
|
||
self.controls["joint_sz_label"].setObjectName("jointSZLabel")
|
||
|
||
self.controls["joint_sz_input"] = QtWidgets.QLineEdit("1.0")
|
||
self.controls["joint_sz_input"].setObjectName("jointSZInput")
|
||
|
||
# 关节属性按钮
|
||
self.buttons["apply_joint_properties"] = QtWidgets.QPushButton(LANG.get("apply", "应用"))
|
||
self.buttons["apply_joint_properties"].setObjectName("applyJointPropertiesButton")
|
||
|
||
self.buttons["reset_joint_properties"] = QtWidgets.QPushButton(LANG.get("reset", "重置"))
|
||
self.buttons["reset_joint_properties"].setObjectName("resetJointPropertiesButton")
|
||
|
||
# 右侧面板控件 - 绑定工具
|
||
self.controls["binding_tools_group"] = QtWidgets.QGroupBox(LANG.get("binding_tools", "绑定工具"))
|
||
self.controls["binding_tools_group"].setObjectName("bindingToolsGroup")
|
||
|
||
# 绑定工具按钮
|
||
self.buttons["create_binding"] = QtWidgets.QPushButton(LANG.get("create_binding", "创建绑定"))
|
||
self.buttons["create_binding"].setObjectName("createBindingButton")
|
||
|
||
self.buttons["copy_skin"] = QtWidgets.QPushButton(LANG.get("copy_skin", "复制蒙皮"))
|
||
self.buttons["copy_skin"].setObjectName("copySkinButton")
|
||
|
||
self.buttons["mirror_skin"] = QtWidgets.QPushButton(LANG.get("mirror_skin", "镜像蒙皮"))
|
||
self.buttons["mirror_skin"].setObjectName("mirrorSkinButton")
|
||
|
||
self.buttons["paint_weights"] = QtWidgets.QPushButton(LANG.get("paint_weights", "绘制权重"))
|
||
self.buttons["paint_weights"].setObjectName("paintWeightsButton")
|
||
|
||
# 底部工具面板
|
||
# DNA部分
|
||
self.controls["dna_group"] = QtWidgets.QGroupBox(LANG.get("dna", "DNA"))
|
||
self.controls["dna_group"].setObjectName("dnaGroup")
|
||
|
||
self.buttons["import_dna"] = QtWidgets.QPushButton(LANG.get("import_dna", "导入DNA"))
|
||
self.buttons["import_dna"].setObjectName("importDnaButton")
|
||
|
||
self.buttons["export_dna"] = QtWidgets.QPushButton(LANG.get("export_dna", "导出DNA"))
|
||
self.buttons["export_dna"].setObjectName("exportDnaButton")
|
||
|
||
self.buttons["calibrate_dna"] = QtWidgets.QPushButton(LANG.get("calibrate_dna", "校准DNA"))
|
||
self.buttons["calibrate_dna"].setObjectName("calibrateDnaButton")
|
||
|
||
# 骨骼部分
|
||
self.controls["skeleton_tools_group"] = QtWidgets.QGroupBox(LANG.get("skeleton_tools", "骨骼工具"))
|
||
self.controls["skeleton_tools_group"].setObjectName("skeletonToolsGroup")
|
||
|
||
self.buttons["import_skeleton"] = QtWidgets.QPushButton(LANG.get("import_skeleton", "导入骨骼"))
|
||
self.buttons["import_skeleton"].setObjectName("importSkeletonButton")
|
||
|
||
self.buttons["export_skeleton"] = QtWidgets.QPushButton(LANG.get("export_skeleton", "导出骨骼"))
|
||
self.buttons["export_skeleton"].setObjectName("exportSkeletonButton")
|
||
|
||
self.buttons["calibrate_skeleton"] = QtWidgets.QPushButton(LANG.get("calibrate_skeleton", "校准骨骼"))
|
||
self.buttons["calibrate_skeleton"].setObjectName("calibrateSkeletonButton")
|
||
|
||
# 工具部分
|
||
self.controls["rigging_tools_group"] = QtWidgets.QGroupBox(LANG.get("rigging_tools", "绑定工具"))
|
||
self.controls["rigging_tools_group"].setObjectName("riggingToolsGroup")
|
||
|
||
self.buttons["generate_controllers"] = QtWidgets.QPushButton(LANG.get("generate_controllers", "生成控制器"))
|
||
self.buttons["generate_controllers"].setObjectName("generateControllersButton")
|
||
|
||
self.buttons["generate_body"] = QtWidgets.QPushButton(LANG.get("generate_body", "生成身体"))
|
||
self.buttons["generate_body"].setObjectName("generateBodyButton")
|
||
|
||
self.buttons["clean_rigging"] = QtWidgets.QPushButton(LANG.get("clean_rigging", "清理绑定"))
|
||
self.buttons["clean_rigging"].setObjectName("cleanRiggingButton")
|
||
|
||
#========================================= LAYOUT =======================================
|
||
def create_layouts(self):
|
||
"""
|
||
创建绑定系统UI布局
|
||
组织控件的排列和层次结构
|
||
"""
|
||
# 主布局
|
||
self.layouts["main_layout"] = QtWidgets.QVBoxLayout(self.main_widget)
|
||
self.layouts["main_layout"].setContentsMargins(2, 2, 2, 2)
|
||
self.layouts["main_layout"].setSpacing(2)
|
||
|
||
# 添加标题标签
|
||
self.layouts["main_layout"].addWidget(self.controls["title_label"])
|
||
|
||
# 创建主分割器
|
||
self.splitters["main_splitter"] = QtWidgets.QSplitter(QtCore.Qt.Horizontal)
|
||
self.splitters["main_splitter"].setObjectName("riggingMainSplitter")
|
||
self.layouts["main_layout"].addWidget(self.splitters["main_splitter"])
|
||
|
||
# 左侧面板布局
|
||
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)
|
||
|
||
# 骨骼组布局
|
||
self.layouts["skeleton_group_layout"] = QtWidgets.QVBoxLayout(self.controls["skeleton_group"])
|
||
self.layouts["skeleton_group_layout"].setContentsMargins(5, 10, 5, 5)
|
||
self.layouts["skeleton_group_layout"].setSpacing(5)
|
||
|
||
# 骨骼列表
|
||
self.layouts["skeleton_group_layout"].addWidget(self.controls["skeleton_list"])
|
||
|
||
# 骨骼操作按钮行
|
||
self.layouts["skeleton_buttons_layout"] = QtWidgets.QHBoxLayout()
|
||
self.layouts["skeleton_buttons_layout"].setContentsMargins(0, 0, 0, 0)
|
||
self.layouts["skeleton_buttons_layout"].setSpacing(2)
|
||
|
||
self.layouts["skeleton_buttons_layout"].addWidget(self.buttons["add_joint"])
|
||
self.layouts["skeleton_buttons_layout"].addWidget(self.buttons["remove_joint"])
|
||
self.layouts["skeleton_buttons_layout"].addWidget(self.buttons["duplicate_joint"])
|
||
|
||
self.layouts["skeleton_group_layout"].addLayout(self.layouts["skeleton_buttons_layout"])
|
||
|
||
# 控制器组布局
|
||
self.layouts["controller_group_layout"] = QtWidgets.QVBoxLayout(self.controls["controller_group"])
|
||
self.layouts["controller_group_layout"].setContentsMargins(5, 10, 5, 5)
|
||
self.layouts["controller_group_layout"].setSpacing(5)
|
||
|
||
# 控制器列表
|
||
self.layouts["controller_group_layout"].addWidget(self.controls["controller_list"])
|
||
|
||
# 控制器操作按钮行
|
||
self.layouts["controller_buttons_layout"] = QtWidgets.QHBoxLayout()
|
||
self.layouts["controller_buttons_layout"].setContentsMargins(0, 0, 0, 0)
|
||
self.layouts["controller_buttons_layout"].setSpacing(2)
|
||
|
||
self.layouts["controller_buttons_layout"].addWidget(self.buttons["add_controller"])
|
||
self.layouts["controller_buttons_layout"].addWidget(self.buttons["remove_controller"])
|
||
self.layouts["controller_buttons_layout"].addWidget(self.buttons["duplicate_controller"])
|
||
|
||
self.layouts["controller_group_layout"].addLayout(self.layouts["controller_buttons_layout"])
|
||
|
||
# 添加组到左侧面板
|
||
self.layouts["left_layout"].addWidget(self.controls["skeleton_group"])
|
||
self.layouts["left_layout"].addWidget(self.controls["controller_group"])
|
||
|
||
# 右侧面板布局
|
||
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)
|
||
|
||
# 关节属性组布局
|
||
self.layouts["joint_properties_layout"] = QtWidgets.QVBoxLayout(self.controls["joint_properties_group"])
|
||
self.layouts["joint_properties_layout"].setContentsMargins(5, 10, 5, 5)
|
||
self.layouts["joint_properties_layout"].setSpacing(5)
|
||
|
||
# 关节名称行
|
||
self.layouts["joint_name_layout"] = QtWidgets.QHBoxLayout()
|
||
self.layouts["joint_name_layout"].setContentsMargins(0, 0, 0, 0)
|
||
self.layouts["joint_name_layout"].setSpacing(5)
|
||
|
||
self.layouts["joint_name_layout"].addWidget(self.controls["joint_name_label"])
|
||
self.layouts["joint_name_layout"].addWidget(self.controls["joint_name_input"])
|
||
|
||
self.layouts["joint_properties_layout"].addLayout(self.layouts["joint_name_layout"])
|
||
|
||
# 关节位置行
|
||
self.layouts["joint_position_layout"] = QtWidgets.QVBoxLayout()
|
||
self.layouts["joint_position_layout"].setContentsMargins(0, 0, 0, 0)
|
||
self.layouts["joint_position_layout"].setSpacing(2)
|
||
|
||
self.layouts["joint_position_layout"].addWidget(self.controls["joint_position_label"])
|
||
|
||
# 位置坐标行
|
||
self.layouts["position_coords_layout"] = QtWidgets.QGridLayout()
|
||
self.layouts["position_coords_layout"].setContentsMargins(0, 0, 0, 0)
|
||
self.layouts["position_coords_layout"].setSpacing(5)
|
||
|
||
self.layouts["position_coords_layout"].addWidget(self.controls["joint_x_label"], 0, 0)
|
||
self.layouts["position_coords_layout"].addWidget(self.controls["joint_x_input"], 0, 1)
|
||
self.layouts["position_coords_layout"].addWidget(self.controls["joint_y_label"], 1, 0)
|
||
self.layouts["position_coords_layout"].addWidget(self.controls["joint_y_input"], 1, 1)
|
||
self.layouts["position_coords_layout"].addWidget(self.controls["joint_z_label"], 2, 0)
|
||
self.layouts["position_coords_layout"].addWidget(self.controls["joint_z_input"], 2, 1)
|
||
|
||
self.layouts["joint_position_layout"].addLayout(self.layouts["position_coords_layout"])
|
||
self.layouts["joint_properties_layout"].addLayout(self.layouts["joint_position_layout"])
|
||
|
||
# 关节旋转行
|
||
self.layouts["joint_rotation_layout"] = QtWidgets.QVBoxLayout()
|
||
self.layouts["joint_rotation_layout"].setContentsMargins(0, 0, 0, 0)
|
||
self.layouts["joint_rotation_layout"].setSpacing(2)
|
||
|
||
self.layouts["joint_rotation_layout"].addWidget(self.controls["joint_rotation_label"])
|
||
|
||
# 旋转坐标行
|
||
self.layouts["rotation_coords_layout"] = QtWidgets.QGridLayout()
|
||
self.layouts["rotation_coords_layout"].setContentsMargins(0, 0, 0, 0)
|
||
self.layouts["rotation_coords_layout"].setSpacing(5)
|
||
|
||
self.layouts["rotation_coords_layout"].addWidget(self.controls["joint_rx_label"], 0, 0)
|
||
self.layouts["rotation_coords_layout"].addWidget(self.controls["joint_rx_input"], 0, 1)
|
||
self.layouts["rotation_coords_layout"].addWidget(self.controls["joint_ry_label"], 1, 0)
|
||
self.layouts["rotation_coords_layout"].addWidget(self.controls["joint_ry_input"], 1, 1)
|
||
self.layouts["rotation_coords_layout"].addWidget(self.controls["joint_rz_label"], 2, 0)
|
||
self.layouts["rotation_coords_layout"].addWidget(self.controls["joint_rz_input"], 2, 1)
|
||
|
||
self.layouts["joint_rotation_layout"].addLayout(self.layouts["rotation_coords_layout"])
|
||
self.layouts["joint_properties_layout"].addLayout(self.layouts["joint_rotation_layout"])
|
||
|
||
# 关节缩放行
|
||
self.layouts["joint_scale_layout"] = QtWidgets.QVBoxLayout()
|
||
self.layouts["joint_scale_layout"].setContentsMargins(0, 0, 0, 0)
|
||
self.layouts["joint_scale_layout"].setSpacing(2)
|
||
|
||
self.layouts["joint_scale_layout"].addWidget(self.controls["joint_scale_label"])
|
||
|
||
# 缩放坐标行
|
||
self.layouts["scale_coords_layout"] = QtWidgets.QGridLayout()
|
||
self.layouts["scale_coords_layout"].setContentsMargins(0, 0, 0, 0)
|
||
self.layouts["scale_coords_layout"].setSpacing(5)
|
||
|
||
self.layouts["scale_coords_layout"].addWidget(self.controls["joint_sx_label"], 0, 0)
|
||
self.layouts["scale_coords_layout"].addWidget(self.controls["joint_sx_input"], 0, 1)
|
||
self.layouts["scale_coords_layout"].addWidget(self.controls["joint_sy_label"], 1, 0)
|
||
self.layouts["scale_coords_layout"].addWidget(self.controls["joint_sy_input"], 1, 1)
|
||
self.layouts["scale_coords_layout"].addWidget(self.controls["joint_sz_label"], 2, 0)
|
||
self.layouts["scale_coords_layout"].addWidget(self.controls["joint_sz_input"], 2, 1)
|
||
|
||
self.layouts["joint_scale_layout"].addLayout(self.layouts["scale_coords_layout"])
|
||
self.layouts["joint_properties_layout"].addLayout(self.layouts["joint_scale_layout"])
|
||
|
||
# 属性按钮行
|
||
self.layouts["properties_buttons_layout"] = QtWidgets.QHBoxLayout()
|
||
self.layouts["properties_buttons_layout"].setContentsMargins(0, 0, 0, 0)
|
||
self.layouts["properties_buttons_layout"].setSpacing(5)
|
||
|
||
self.layouts["properties_buttons_layout"].addWidget(self.buttons["apply_joint_properties"])
|
||
self.layouts["properties_buttons_layout"].addWidget(self.buttons["reset_joint_properties"])
|
||
|
||
self.layouts["joint_properties_layout"].addLayout(self.layouts["properties_buttons_layout"])
|
||
|
||
# 绑定工具组布局
|
||
self.layouts["binding_tools_layout"] = QtWidgets.QVBoxLayout(self.controls["binding_tools_group"])
|
||
self.layouts["binding_tools_layout"].setContentsMargins(5, 10, 5, 5)
|
||
self.layouts["binding_tools_layout"].setSpacing(5)
|
||
|
||
# 绑定工具按钮网格
|
||
self.layouts["binding_tools_grid"] = QtWidgets.QGridLayout()
|
||
self.layouts["binding_tools_grid"].setContentsMargins(0, 0, 0, 0)
|
||
self.layouts["binding_tools_grid"].setSpacing(5)
|
||
|
||
self.layouts["binding_tools_grid"].addWidget(self.buttons["create_binding"], 0, 0)
|
||
self.layouts["binding_tools_grid"].addWidget(self.buttons["copy_skin"], 0, 1)
|
||
self.layouts["binding_tools_grid"].addWidget(self.buttons["mirror_skin"], 1, 0)
|
||
self.layouts["binding_tools_grid"].addWidget(self.buttons["paint_weights"], 1, 1)
|
||
|
||
self.layouts["binding_tools_layout"].addLayout(self.layouts["binding_tools_grid"])
|
||
|
||
# 添加组到右侧面板
|
||
self.layouts["right_layout"].addWidget(self.controls["joint_properties_group"])
|
||
self.layouts["right_layout"].addWidget(self.controls["binding_tools_group"])
|
||
|
||
# 底部工具面板
|
||
self.layouts["bottom_panel"] = QtWidgets.QHBoxLayout()
|
||
self.layouts["bottom_panel"].setContentsMargins(2, 2, 2, 2)
|
||
self.layouts["bottom_panel"].setSpacing(5)
|
||
|
||
# DNA组布局
|
||
self.layouts["dna_layout"] = QtWidgets.QVBoxLayout(self.controls["dna_group"])
|
||
self.layouts["dna_layout"].setContentsMargins(5, 10, 5, 5)
|
||
self.layouts["dna_layout"].setSpacing(5)
|
||
|
||
self.layouts["dna_layout"].addWidget(self.buttons["import_dna"])
|
||
self.layouts["dna_layout"].addWidget(self.buttons["export_dna"])
|
||
self.layouts["dna_layout"].addWidget(self.buttons["calibrate_dna"])
|
||
|
||
# 骨骼工具组布局
|
||
self.layouts["skeleton_tools_layout"] = QtWidgets.QVBoxLayout(self.controls["skeleton_tools_group"])
|
||
self.layouts["skeleton_tools_layout"].setContentsMargins(5, 10, 5, 5)
|
||
self.layouts["skeleton_tools_layout"].setSpacing(5)
|
||
|
||
self.layouts["skeleton_tools_layout"].addWidget(self.buttons["import_skeleton"])
|
||
self.layouts["skeleton_tools_layout"].addWidget(self.buttons["export_skeleton"])
|
||
self.layouts["skeleton_tools_layout"].addWidget(self.buttons["calibrate_skeleton"])
|
||
|
||
# 绑定工具组布局
|
||
self.layouts["rigging_tools_layout"] = QtWidgets.QVBoxLayout(self.controls["rigging_tools_group"])
|
||
self.layouts["rigging_tools_layout"].setContentsMargins(5, 10, 5, 5)
|
||
self.layouts["rigging_tools_layout"].setSpacing(5)
|
||
|
||
self.layouts["rigging_tools_layout"].addWidget(self.buttons["generate_controllers"])
|
||
self.layouts["rigging_tools_layout"].addWidget(self.buttons["generate_body"])
|
||
self.layouts["rigging_tools_layout"].addWidget(self.buttons["clean_rigging"])
|
||
|
||
# 添加组到底部面板
|
||
self.layouts["bottom_panel"].addWidget(self.controls["dna_group"])
|
||
self.layouts["bottom_panel"].addWidget(self.controls["skeleton_tools_group"])
|
||
self.layouts["bottom_panel"].addWidget(self.controls["rigging_tools_group"])
|
||
|
||
# 添加底部面板到主布局
|
||
self.layouts["main_layout"].addLayout(self.layouts["bottom_panel"])
|
||
|
||
# 将左右面板添加到主分割器
|
||
self.splitters["main_splitter"].addWidget(self.controls["left_panel"])
|
||
self.splitters["main_splitter"].addWidget(self.controls["right_panel"])
|
||
|
||
# 设置分割器初始大小和伸缩因子
|
||
self.splitters["main_splitter"].setSizes([500, 500])
|
||
|
||
# 设置分割器的伸缩因子,确保左右栏能够自动调整宽度
|
||
for i in range(self.splitters["main_splitter"].count()):
|
||
self.splitters["main_splitter"].setStretchFactor(i, 1)
|
||
|
||
#======================================= CONNECTION =====================================
|
||
def create_connections(self):
|
||
"""
|
||
创建绑定系统UI信号和槽连接
|
||
将按钮点击等事件与相应的处理函数连接
|
||
"""
|
||
# 左侧面板 - 骨骼列表操作
|
||
self.buttons["add_joint"].clicked.connect(self.add_joint)
|
||
self.buttons["remove_joint"].clicked.connect(self.remove_joint)
|
||
self.buttons["duplicate_joint"].clicked.connect(self.duplicate_joint)
|
||
self.controls["skeleton_list"].itemSelectionChanged.connect(self.on_joint_selection_changed)
|
||
|
||
# 左侧面板 - 控制器列表操作
|
||
self.buttons["add_controller"].clicked.connect(self.add_controller)
|
||
self.buttons["remove_controller"].clicked.connect(self.remove_controller)
|
||
self.buttons["duplicate_controller"].clicked.connect(self.duplicate_controller)
|
||
self.controls["controller_list"].itemSelectionChanged.connect(self.on_controller_selection_changed)
|
||
|
||
# 右侧面板 - 关节属性
|
||
self.buttons["apply_joint_properties"].clicked.connect(self.apply_joint_properties)
|
||
self.buttons["reset_joint_properties"].clicked.connect(self.reset_joint_properties)
|
||
|
||
# 坐标输入框修改事件
|
||
self.controls["joint_name_input"].textChanged.connect(self.on_joint_name_changed)
|
||
self.controls["joint_x_input"].textChanged.connect(lambda: self.on_joint_position_changed("x"))
|
||
self.controls["joint_y_input"].textChanged.connect(lambda: self.on_joint_position_changed("y"))
|
||
self.controls["joint_z_input"].textChanged.connect(lambda: self.on_joint_position_changed("z"))
|
||
self.controls["joint_rx_input"].textChanged.connect(lambda: self.on_joint_rotation_changed("x"))
|
||
self.controls["joint_ry_input"].textChanged.connect(lambda: self.on_joint_rotation_changed("y"))
|
||
self.controls["joint_rz_input"].textChanged.connect(lambda: self.on_joint_rotation_changed("z"))
|
||
self.controls["joint_sx_input"].textChanged.connect(lambda: self.on_joint_scale_changed("x"))
|
||
self.controls["joint_sy_input"].textChanged.connect(lambda: self.on_joint_scale_changed("y"))
|
||
self.controls["joint_sz_input"].textChanged.connect(lambda: self.on_joint_scale_changed("z"))
|
||
|
||
# 右侧面板 - 绑定工具
|
||
self.buttons["create_binding"].clicked.connect(self.create_binding)
|
||
self.buttons["copy_skin"].clicked.connect(self.copy_skin)
|
||
self.buttons["mirror_skin"].clicked.connect(self.mirror_skin)
|
||
self.buttons["paint_weights"].clicked.connect(self.paint_weights)
|
||
|
||
# 底部工具面板 - DNA操作
|
||
self.buttons["import_dna"].clicked.connect(self.import_dna)
|
||
self.buttons["export_dna"].clicked.connect(self.export_dna)
|
||
self.buttons["calibrate_dna"].clicked.connect(self.calibrate_dna)
|
||
|
||
# 底部工具面板 - 骨骼工具
|
||
self.buttons["import_skeleton"].clicked.connect(self.import_skeleton)
|
||
self.buttons["export_skeleton"].clicked.connect(self.export_skeleton)
|
||
self.buttons["calibrate_skeleton"].clicked.connect(self.calibrate_skeleton)
|
||
|
||
# 底部工具面板 - 绑定工具
|
||
self.buttons["generate_controllers"].clicked.connect(self.generate_controllers)
|
||
self.buttons["generate_body"].clicked.connect(self.generate_body)
|
||
self.buttons["clean_rigging"].clicked.connect(self.clean_rigging)
|
||
|
||
# 分割器移动事件
|
||
self.splitters["main_splitter"].splitterMoved.connect(self.on_splitter_moved)
|
||
|
||
# 添加显示事件处理
|
||
self.showEvent = self.on_show_event |