Update
This commit is contained in:
parent
02bc3822af
commit
4fb8654dfc
@ -1,81 +1,128 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import sys
|
||||
from maya import cmds
|
||||
from PySide2 import QtCore, QtGui, QtWidgets
|
||||
import maya.OpenMayaUI as omui
|
||||
from PySide2 import QtWidgets, QtCore
|
||||
from shiboken2 import wrapInstance
|
||||
|
||||
from . import config
|
||||
from .ui import menu, toolshelf
|
||||
from .utils import maya_utils
|
||||
from scripts import config
|
||||
from scripts.ui import menu, toolshelf, meshes, rigging, behaviour, definition
|
||||
|
||||
class MetaFusion(QtWidgets.QMainWindow):
|
||||
def __init__(self, parent=None):
|
||||
super(MetaFusion, self).__init__(parent)
|
||||
self._setup_ui()
|
||||
self._create_connections()
|
||||
self._load_style()
|
||||
|
||||
# 设置窗口标题和基本属性
|
||||
self.setWindowTitle("MetaFusion")
|
||||
self.setMinimumSize(1200, 800)
|
||||
def _setup_ui(self):
|
||||
"""设置UI布局"""
|
||||
# === 设置窗口属性 ===
|
||||
self.setWindowTitle(f"{config.TOOL_NAME} {config.TOOL_VERSION}")
|
||||
# 设置初始大小和最小大小
|
||||
self.resize(550, 700) # 初始大小
|
||||
self.setMinimumSize(550, 700) # 最小大小限制
|
||||
|
||||
# 加载样式表
|
||||
style_file = os.path.join(os.path.dirname(__file__), "ui", "style.qss")
|
||||
with open(style_file, "r", encoding="utf-8") as f:
|
||||
self.setStyleSheet(f.read())
|
||||
# === 创建中心部件 ===
|
||||
self.central_widget = QtWidgets.QWidget()
|
||||
self.setCentralWidget(self.central_widget)
|
||||
|
||||
# 创建主窗口部件
|
||||
self.main_widget = QtWidgets.QWidget()
|
||||
self.setCentralWidget(self.main_widget)
|
||||
# === Main Layout ===
|
||||
self.main_layout = QtWidgets.QVBoxLayout(self.central_widget)
|
||||
self.main_layout.setContentsMargins(0, 0, 0, 0)
|
||||
self.main_layout.setSpacing(0)
|
||||
|
||||
# 创建主布局
|
||||
self.main_layout = QtWidgets.QVBoxLayout(self.main_widget)
|
||||
# === 创建菜单栏 ===
|
||||
self.menu_bar = menu.MenuBar(self)
|
||||
self.setMenuBar(self.menu_bar)
|
||||
|
||||
# 初始化UI组件
|
||||
self._init_ui()
|
||||
|
||||
def _init_ui(self):
|
||||
"""初始化UI组件"""
|
||||
# 创建工具架
|
||||
# === 创建工具架 ===
|
||||
self.tool_shelf = toolshelf.ToolShelf(self)
|
||||
self.main_layout.addWidget(self.tool_shelf)
|
||||
|
||||
# 创建标签页
|
||||
# === 创建标签页 ===
|
||||
self.tab_widget = QtWidgets.QTabWidget()
|
||||
self.main_layout.addWidget(self.tab_widget)
|
||||
|
||||
# 添加各个功能页面
|
||||
self._add_meshes_tab()
|
||||
self._add_rigging_tab()
|
||||
self._add_behaviour_tab()
|
||||
self._add_definition_tab()
|
||||
self._create_tabs()
|
||||
|
||||
def _add_meshes_tab(self):
|
||||
"""添加模型页面"""
|
||||
from .ui.meshes import MeshesTab
|
||||
meshes_widget = MeshesTab()
|
||||
self.tab_widget.addTab(meshes_widget, "模型")
|
||||
# === 创建状态栏 ===
|
||||
self.status_bar = self._create_status_bar()
|
||||
self.setStatusBar(self.status_bar)
|
||||
|
||||
def _add_rigging_tab(self):
|
||||
"""添加绑定页面"""
|
||||
from .ui.rigging import RiggingTab
|
||||
rigging_widget = RiggingTab()
|
||||
self.tab_widget.addTab(rigging_widget, "绑定")
|
||||
# 设置窗口位置居中
|
||||
self._center_window()
|
||||
|
||||
def _center_window(self):
|
||||
"""将窗口居中显示"""
|
||||
# 获取主屏幕几何信息
|
||||
screen = QtWidgets.QApplication.primaryScreen().geometry()
|
||||
# 计算窗口居中位置
|
||||
x = (screen.width() - self.width()) // 2
|
||||
y = (screen.height() - self.height()) // 2
|
||||
# 移动窗口
|
||||
self.move(x, y)
|
||||
|
||||
def _add_behaviour_tab(self):
|
||||
"""添加行为页面"""
|
||||
from .ui.behaviour import BehaviourTab
|
||||
behaviour_widget = BehaviourTab()
|
||||
self.tab_widget.addTab(behaviour_widget, "行为")
|
||||
def _create_tabs(self):
|
||||
"""创建标签页"""
|
||||
# Meshes标签页
|
||||
self.meshes_tab = meshes.MeshesTab()
|
||||
self.tab_widget.addTab(self.meshes_tab, "模型")
|
||||
|
||||
# Rigging标签页
|
||||
self.rigging_tab = rigging.RiggingTab()
|
||||
self.tab_widget.addTab(self.rigging_tab, "绑定")
|
||||
|
||||
def _add_definition_tab(self):
|
||||
"""添加定义页面"""
|
||||
from .ui.definition import DefinitionTab
|
||||
definition_widget = DefinitionTab()
|
||||
self.tab_widget.addTab(definition_widget, "定义")
|
||||
# Behaviour标签页
|
||||
self.behaviour_tab = behaviour.BehaviourTab()
|
||||
self.tab_widget.addTab(self.behaviour_tab, "行为")
|
||||
|
||||
# Definition标签页
|
||||
self.definition_tab = definition.DefinitionTab()
|
||||
self.tab_widget.addTab(self.definition_tab, "定义")
|
||||
|
||||
def _create_status_bar(self):
|
||||
"""创建状态栏"""
|
||||
# === Widget ===
|
||||
status_bar = QtWidgets.QStatusBar()
|
||||
|
||||
# 添加版本信息
|
||||
version_label = QtWidgets.QLabel(f"{config.TOOL_VERSION}")
|
||||
status_bar.addPermanentWidget(version_label)
|
||||
|
||||
# 添加Maya版本信息
|
||||
maya_version_label = QtWidgets.QLabel(f"Maya {config.MAYA_VERSION}")
|
||||
status_bar.addPermanentWidget(maya_version_label)
|
||||
|
||||
# 添加Python版本信息
|
||||
python_version_label = QtWidgets.QLabel(f"Python {config.PYTHON_VERSION}")
|
||||
status_bar.addPermanentWidget(python_version_label)
|
||||
|
||||
return status_bar
|
||||
|
||||
def _load_style(self):
|
||||
"""加载样式表"""
|
||||
try:
|
||||
with open(config.TOOL_STYLE_FILE, "r", encoding="utf-8") as f:
|
||||
style = f.read()
|
||||
self.setStyleSheet(style)
|
||||
except Exception as e:
|
||||
print(f"加载样式表失败: {str(e)}")
|
||||
|
||||
def _create_connections(self):
|
||||
"""创建信号连接"""
|
||||
# 标签页切换
|
||||
self.tab_widget.currentChanged.connect(self._on_tab_changed)
|
||||
|
||||
def _on_tab_changed(self, index):
|
||||
"""标签页切换事件"""
|
||||
tab_name = self.tab_widget.tabText(index)
|
||||
self.status_bar.showMessage(f"当前页面: {tab_name}")
|
||||
|
||||
def closeEvent(self, event):
|
||||
"""关闭窗口事件"""
|
||||
# TODO: 实现关闭前的保存提示等逻辑
|
||||
event.accept()
|
||||
|
||||
|
||||
def show():
|
||||
@ -87,3 +134,7 @@ def show():
|
||||
global meta_fusion_window
|
||||
meta_fusion_window = MetaFusion(parent=maya_main_window)
|
||||
meta_fusion_window.show()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
show()
|
||||
|
@ -32,6 +32,169 @@ except ImportError:
|
||||
wrapInstance = None
|
||||
|
||||
class BehaviourTab(QtWidgets.QWidget):
|
||||
def __init__(self, parent=None):
|
||||
super(BehaviourTab, self).__init__(parent)
|
||||
self._setup_ui()
|
||||
self._create_connections()
|
||||
|
||||
def _setup_ui(self):
|
||||
"""设置UI布局"""
|
||||
# 创建主布局
|
||||
self.main_layout = QtWidgets.QHBoxLayout(self)
|
||||
self.main_layout.setContentsMargins(2, 2, 2, 2)
|
||||
self.main_layout.setSpacing(2)
|
||||
|
||||
# 创建左右两个主面板
|
||||
self.raw_control_widget = self._create_raw_control()
|
||||
self.blend_shapes_widget = self._create_blend_shapes()
|
||||
|
||||
self.main_layout.addWidget(self.raw_control_widget)
|
||||
self.main_layout.addWidget(self.blend_shapes_widget)
|
||||
|
||||
def _create_raw_control(self):
|
||||
"""创建Raw Control部分"""
|
||||
# === Widget ===
|
||||
widget = QtWidgets.QWidget()
|
||||
|
||||
# === Layout ===
|
||||
layout = QtWidgets.QVBoxLayout(widget)
|
||||
layout.setContentsMargins(5, 5, 5, 5)
|
||||
layout.setSpacing(5)
|
||||
|
||||
# 标题
|
||||
title_layout = QtWidgets.QHBoxLayout()
|
||||
title_label = QtWidgets.QLabel("Raw Control [814/814]")
|
||||
title_layout.addWidget(title_label)
|
||||
layout.addLayout(title_layout)
|
||||
|
||||
# 搜索框
|
||||
self.search_edit = QtWidgets.QLineEdit()
|
||||
self.search_edit.setPlaceholderText("搜索...")
|
||||
layout.addWidget(self.search_edit)
|
||||
|
||||
# BlendShape列表
|
||||
self.blend_list = QtWidgets.QListWidget()
|
||||
layout.addWidget(self.blend_list)
|
||||
|
||||
# 数值调节
|
||||
value_layout = QtWidgets.QHBoxLayout()
|
||||
self.value_spin = QtWidgets.QDoubleSpinBox()
|
||||
self.value_spin.setValue(0.010)
|
||||
self.value_spin.setDecimals(3)
|
||||
value_layout.addWidget(self.value_spin)
|
||||
layout.addLayout(value_layout)
|
||||
|
||||
# 过滤按钮组
|
||||
filter_layout = QtWidgets.QHBoxLayout()
|
||||
self.filter_buttons = []
|
||||
for text in ["全部", "2", "3", "4", "5", "6"]:
|
||||
btn = QtWidgets.QPushButton(text)
|
||||
btn.setCheckable(True)
|
||||
filter_layout.addWidget(btn)
|
||||
self.filter_buttons.append(btn)
|
||||
layout.addLayout(filter_layout)
|
||||
|
||||
return widget
|
||||
|
||||
def _create_blend_shapes(self):
|
||||
"""创建Related Blend Shapes部分"""
|
||||
# === Widget ===
|
||||
widget = QtWidgets.QWidget()
|
||||
|
||||
# === Layout ===
|
||||
layout = QtWidgets.QVBoxLayout(widget)
|
||||
layout.setContentsMargins(5, 5, 5, 5)
|
||||
layout.setSpacing(5)
|
||||
|
||||
# 标题
|
||||
title_layout = QtWidgets.QHBoxLayout()
|
||||
title_label = QtWidgets.QLabel("Related Blend Shapes [858/858]")
|
||||
title_layout.addWidget(title_label)
|
||||
layout.addLayout(title_layout)
|
||||
|
||||
# BlendShape列表
|
||||
self.related_list = QtWidgets.QListWidget()
|
||||
layout.addWidget(self.related_list)
|
||||
|
||||
# 数值调节
|
||||
value_layout = QtWidgets.QHBoxLayout()
|
||||
self.related_value_spin = QtWidgets.QDoubleSpinBox()
|
||||
self.related_value_spin.setValue(0.000)
|
||||
self.related_value_spin.setDecimals(3)
|
||||
value_layout.addWidget(self.related_value_spin)
|
||||
layout.addLayout(value_layout)
|
||||
|
||||
# 操作按钮组 - 第一行
|
||||
op_layout1 = QtWidgets.QHBoxLayout()
|
||||
op_buttons1 = [
|
||||
("翻转目标", "flip.png"),
|
||||
("镜像目标", "mirror.png"),
|
||||
("查找翻转目标", "find_flip.png")
|
||||
]
|
||||
for text, icon in op_buttons1:
|
||||
btn = QtWidgets.QPushButton(text)
|
||||
if icon:
|
||||
btn.setIcon(QtGui.QIcon(f"{config.ICONS_PATH}/{icon}"))
|
||||
op_layout1.addWidget(btn)
|
||||
layout.addLayout(op_layout1)
|
||||
|
||||
# 操作按钮组 - 第二行
|
||||
op_layout2 = QtWidgets.QHBoxLayout()
|
||||
op_buttons2 = [
|
||||
("添加混合目标", "add.png"),
|
||||
("删除混合目标", "delete.png"),
|
||||
("批量混合目标", "batch.png")
|
||||
]
|
||||
for text, icon in op_buttons2:
|
||||
btn = QtWidgets.QPushButton(text)
|
||||
if icon:
|
||||
btn.setIcon(QtGui.QIcon(f"{config.ICONS_PATH}/{icon}"))
|
||||
op_layout2.addWidget(btn)
|
||||
layout.addLayout(op_layout2)
|
||||
|
||||
# 功能按钮组
|
||||
func_layout = QtWidgets.QHBoxLayout()
|
||||
func_buttons = ["PSD", "BSE", "KEY", "MIR", "ARK", "CTR"]
|
||||
for text in func_buttons:
|
||||
btn = QtWidgets.QPushButton(text)
|
||||
btn.setFixedWidth(40)
|
||||
func_layout.addWidget(btn)
|
||||
layout.addLayout(func_layout)
|
||||
|
||||
return widget
|
||||
|
||||
def _create_connections(self):
|
||||
"""创建信号连接"""
|
||||
# 搜索框
|
||||
self.search_edit.textChanged.connect(self._filter_blend_shapes)
|
||||
|
||||
# 数值调节
|
||||
self.value_spin.valueChanged.connect(self._update_raw_value)
|
||||
self.related_value_spin.valueChanged.connect(self._update_related_value)
|
||||
|
||||
# 过滤按钮组
|
||||
for btn in self.filter_buttons:
|
||||
btn.clicked.connect(self._apply_filter)
|
||||
|
||||
# ================================ 事件函数 ================================
|
||||
def _filter_blend_shapes(self, text):
|
||||
"""过滤BlendShape列表"""
|
||||
# TODO: 实现过滤逻辑
|
||||
pass
|
||||
|
||||
def _update_raw_value(self, value):
|
||||
"""更新Raw Control值"""
|
||||
# TODO: 实现更新逻辑
|
||||
pass
|
||||
|
||||
def _update_related_value(self, value):
|
||||
"""更新Related Blend Shapes值"""
|
||||
# TODO: 实现更新逻辑
|
||||
pass
|
||||
|
||||
def _apply_filter(self):
|
||||
"""应用过滤器"""
|
||||
# TODO: 实现过滤逻辑
|
||||
pass
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
@ -32,6 +32,260 @@ except ImportError:
|
||||
wrapInstance = None
|
||||
|
||||
class DefinitionTab(QtWidgets.QWidget):
|
||||
def __init__(self, parent=None):
|
||||
super(DefinitionTab, self).__init__(parent)
|
||||
self._setup_ui()
|
||||
self._create_connections()
|
||||
|
||||
def _setup_ui(self):
|
||||
"""设置UI布局"""
|
||||
# === Main Layout ===
|
||||
self.main_layout = QtWidgets.QHBoxLayout(self)
|
||||
self.main_layout.setContentsMargins(2, 2, 2, 2)
|
||||
self.main_layout.setSpacing(2)
|
||||
|
||||
# 创建左侧和右侧面板
|
||||
self.left_panel = self._create_left_panel()
|
||||
self.right_panel = self._create_right_panel()
|
||||
|
||||
self.main_layout.addWidget(self.left_panel, 1) # 1:3比例
|
||||
self.main_layout.addWidget(self.right_panel, 3)
|
||||
|
||||
def _create_left_panel(self):
|
||||
"""创建左侧面板"""
|
||||
# === Widget ===
|
||||
widget = QtWidgets.QWidget()
|
||||
|
||||
# === Layout ===
|
||||
layout = QtWidgets.QVBoxLayout(widget)
|
||||
layout.setContentsMargins(5, 5, 5, 5)
|
||||
layout.setSpacing(5)
|
||||
|
||||
# LODs列表
|
||||
lod_group = QtWidgets.QGroupBox("LODs")
|
||||
lod_layout = QtWidgets.QVBoxLayout()
|
||||
self.lod_list = QtWidgets.QListWidget()
|
||||
for i in range(8):
|
||||
self.lod_list.addItem(f"LOD {i}")
|
||||
lod_layout.addWidget(self.lod_list)
|
||||
|
||||
# Define Joint按钮
|
||||
self.define_joint_btn = QtWidgets.QPushButton("Define Joint For LOD")
|
||||
lod_layout.addWidget(self.define_joint_btn)
|
||||
|
||||
lod_group.setLayout(lod_layout)
|
||||
layout.addWidget(lod_group)
|
||||
|
||||
return widget
|
||||
|
||||
def _create_right_panel(self):
|
||||
"""创建右侧面板"""
|
||||
# === Widget ===
|
||||
widget = QtWidgets.QWidget()
|
||||
|
||||
# === Layout ===
|
||||
layout = QtWidgets.QVBoxLayout(widget)
|
||||
layout.setContentsMargins(5, 5, 5, 5)
|
||||
layout.setSpacing(5)
|
||||
|
||||
# 创建各个部分
|
||||
self.meshes_widget = self._create_meshes_section()
|
||||
self.joints_widget = self._create_joints_section()
|
||||
self.blend_shapes_widget = self._create_blend_shapes_section()
|
||||
self.animated_map_widget = self._create_animated_map_section()
|
||||
|
||||
# 添加到布局
|
||||
layout.addWidget(self.meshes_widget)
|
||||
layout.addWidget(self.joints_widget)
|
||||
layout.addWidget(self.blend_shapes_widget)
|
||||
layout.addWidget(self.animated_map_widget)
|
||||
|
||||
# 添加操作按钮区域
|
||||
self.operation_widget = self._create_operation_section()
|
||||
layout.addWidget(self.operation_widget)
|
||||
|
||||
return widget
|
||||
|
||||
def _create_meshes_section(self):
|
||||
"""创建Meshes部分"""
|
||||
# === Widget ===
|
||||
group = QtWidgets.QGroupBox("Meshes [010/54]")
|
||||
|
||||
# === Layout ===
|
||||
layout = QtWidgets.QVBoxLayout(group)
|
||||
|
||||
# 列表
|
||||
self.meshes_list = QtWidgets.QListWidget()
|
||||
meshes = [
|
||||
"head_lod0_mesh (000)",
|
||||
"teeth_lod0_mesh (001)",
|
||||
"saliva_lod0_mesh (002)",
|
||||
"eyeLeft_lod0_mesh (003)",
|
||||
"eyeRight_lod0_mesh (004)",
|
||||
"eyeshell_lod0_mesh (005)",
|
||||
"eyelashes_lod0_mesh (006)",
|
||||
"eyeEdge_lod0_mesh (007)"
|
||||
]
|
||||
for mesh in meshes:
|
||||
self.meshes_list.addItem(mesh)
|
||||
|
||||
layout.addWidget(self.meshes_list)
|
||||
|
||||
# Create Geometry按钮
|
||||
self.create_geo_btn = QtWidgets.QPushButton("Create Geometry")
|
||||
layout.addWidget(self.create_geo_btn)
|
||||
|
||||
return group
|
||||
|
||||
def _create_joints_section(self):
|
||||
"""创建Joints部分"""
|
||||
# === Widget ===
|
||||
group = QtWidgets.QGroupBox("Joints [840/870]")
|
||||
|
||||
# === Layout ===
|
||||
layout = QtWidgets.QVBoxLayout(group)
|
||||
|
||||
# 列表
|
||||
self.joints_list = QtWidgets.QListWidget()
|
||||
joints = [
|
||||
"FACIAL_C_NeckB Group: 001",
|
||||
"FACIAL_L_NeckB1 Group: 002",
|
||||
"FACIAL_R_NeckB1 Group: 003",
|
||||
"FACIAL_L_NeckB2 Group: 002",
|
||||
"FACIAL_R_NeckB2 Group: 003",
|
||||
"FACIAL_C12PV_NeckB1 Group: 001"
|
||||
]
|
||||
for joint in joints:
|
||||
self.joints_list.addItem(joint)
|
||||
|
||||
layout.addWidget(self.joints_list)
|
||||
return group
|
||||
|
||||
def _create_blend_shapes_section(self):
|
||||
"""创建Blend Shapes部分"""
|
||||
# === Widget ===
|
||||
group = QtWidgets.QGroupBox("Blend Shapes [782/782]")
|
||||
|
||||
# === Layout ===
|
||||
layout = QtWidgets.QVBoxLayout(group)
|
||||
|
||||
# 列表
|
||||
self.blend_shapes_list = QtWidgets.QListWidget()
|
||||
shapes = [
|
||||
"brow_down_L 000",
|
||||
"brow_down_R 001",
|
||||
"brow_lateral_L 002",
|
||||
"brow_lateral_R 003",
|
||||
"brow_raiseIn_L 004",
|
||||
"brow_raiseIn_R 005"
|
||||
]
|
||||
for shape in shapes:
|
||||
self.blend_shapes_list.addItem(shape)
|
||||
|
||||
layout.addWidget(self.blend_shapes_list)
|
||||
return group
|
||||
|
||||
def _create_animated_map_section(self):
|
||||
"""创建AnimatedMap部分"""
|
||||
# === Widget ===
|
||||
group = QtWidgets.QGroupBox("AnimatedMap [082/82]")
|
||||
|
||||
# === Layout ===
|
||||
layout = QtWidgets.QVBoxLayout(group)
|
||||
|
||||
# 列表
|
||||
self.animated_map_list = QtWidgets.QListWidget()
|
||||
maps = [
|
||||
"head_cm2_color.head_wm2.browsDown 000",
|
||||
"head_cm2_color.head_wm2.browsDown 001",
|
||||
"head_cm2_color.head_wm2.browsLate 002",
|
||||
"head_cm2_color.head_wm2.browsLate 003",
|
||||
"head_cm1_color.head_wm1.browsRais 004",
|
||||
"head_cm1_color.head_wm1.browsRais 005"
|
||||
]
|
||||
for map_item in maps:
|
||||
self.animated_map_list.addItem(map_item)
|
||||
|
||||
layout.addWidget(self.animated_map_list)
|
||||
return group
|
||||
|
||||
def _create_operation_section(self):
|
||||
"""创建操作区域"""
|
||||
# === Widget ===
|
||||
widget = QtWidgets.QWidget()
|
||||
|
||||
# === Layout ===
|
||||
layout = QtWidgets.QVBoxLayout(widget)
|
||||
|
||||
# Write部分
|
||||
write_group = QtWidgets.QGroupBox("Write")
|
||||
write_layout = QtWidgets.QVBoxLayout()
|
||||
write_buttons = [
|
||||
"Write Neutral Pose Joint Position",
|
||||
"Write Geometry",
|
||||
"Write Skin Weights",
|
||||
"Write Blend Shapes Targets"
|
||||
]
|
||||
for text in write_buttons:
|
||||
btn = QtWidgets.QPushButton(text)
|
||||
write_layout.addWidget(btn)
|
||||
write_group.setLayout(write_layout)
|
||||
layout.addWidget(write_group)
|
||||
|
||||
# Create部分
|
||||
create_group = QtWidgets.QGroupBox("Create")
|
||||
create_layout = QtWidgets.QVBoxLayout()
|
||||
create_buttons = [
|
||||
"Create Blend Shapes For Mesh",
|
||||
"Bind Skin For Mesh",
|
||||
"Unbind Skin For Mesh"
|
||||
]
|
||||
for text in create_buttons:
|
||||
btn = QtWidgets.QPushButton(text)
|
||||
create_layout.addWidget(btn)
|
||||
create_group.setLayout(create_layout)
|
||||
layout.addWidget(create_group)
|
||||
|
||||
# Tools部分
|
||||
tools_group = QtWidgets.QGroupBox("Tools")
|
||||
tools_layout = QtWidgets.QVBoxLayout()
|
||||
tools_buttons = [
|
||||
"New Neutral Joint Transform",
|
||||
"Quickly Create Presets"
|
||||
]
|
||||
for text in tools_buttons:
|
||||
btn = QtWidgets.QPushButton(text)
|
||||
tools_layout.addWidget(btn)
|
||||
tools_group.setLayout(tools_layout)
|
||||
layout.addWidget(tools_group)
|
||||
|
||||
return widget
|
||||
|
||||
def _create_connections(self):
|
||||
"""创建信号连接"""
|
||||
# LOD列表选择
|
||||
self.lod_list.currentItemChanged.connect(self._on_lod_changed)
|
||||
|
||||
# Define Joint按钮
|
||||
self.define_joint_btn.clicked.connect(self._on_define_joint)
|
||||
|
||||
# Create Geometry按钮
|
||||
self.create_geo_btn.clicked.connect(self._on_create_geometry)
|
||||
|
||||
# ================================ 事件函数 ================================
|
||||
def _on_lod_changed(self, current, previous):
|
||||
"""LOD选择改变"""
|
||||
# TODO: 实现LOD切换逻辑
|
||||
pass
|
||||
|
||||
def _on_define_joint(self):
|
||||
"""Define Joint按钮点击"""
|
||||
# TODO: 实现Define Joint逻辑
|
||||
pass
|
||||
|
||||
def _on_create_geometry(self):
|
||||
"""Create Geometry按钮点击"""
|
||||
# TODO: 实现Create Geometry逻辑
|
||||
pass
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
@ -31,9 +31,233 @@ except ImportError:
|
||||
QtCore = QtGui = QtWidgets = None
|
||||
wrapInstance = None
|
||||
|
||||
class Menu(QtWidgets.QWidget):
|
||||
class MenuBar(QtWidgets.QMenuBar):
|
||||
def __init__(self, parent=None):
|
||||
super(MenuBar, self).__init__(parent)
|
||||
self._setup_ui()
|
||||
self._create_connections()
|
||||
|
||||
def _setup_ui(self):
|
||||
"""设置UI布局"""
|
||||
# 创建主菜单
|
||||
self.file_menu = self._create_file_menu()
|
||||
self.edit_menu = self._create_edit_menu()
|
||||
self.tools_menu = self._create_tools_menu()
|
||||
self.language_menu = self._create_language_menu()
|
||||
self.help_menu = self._create_help_menu()
|
||||
|
||||
# 添加到菜单栏
|
||||
self.addMenu(self.file_menu)
|
||||
self.addMenu(self.edit_menu)
|
||||
self.addMenu(self.tools_menu)
|
||||
self.addMenu(self.language_menu)
|
||||
self.addMenu(self.help_menu)
|
||||
|
||||
def _create_file_menu(self):
|
||||
"""创建文件菜单"""
|
||||
# === Widget ===
|
||||
menu = QtWidgets.QMenu("文件")
|
||||
|
||||
# === Actions ===
|
||||
self.file_actions = {}
|
||||
actions = [
|
||||
("open_dna", "打开 DNA", "open.png", "Ctrl+O"),
|
||||
("save_dna", "保存 DNA", "save.png", "Ctrl+S"),
|
||||
("load_current", "加载当前项目 DNA", "open.png", ""),
|
||||
None, # 分隔符
|
||||
("rename_blend", "修改混合目标名称", "rename.png", ""),
|
||||
("reset_blend", "重置混合目标名称", "resetname.png", ""),
|
||||
None,
|
||||
("export_fbx", "导出 FBX", "export.png", ""),
|
||||
None,
|
||||
("exit", "退出", "exit.png", "Alt+F4")
|
||||
]
|
||||
|
||||
self._add_menu_actions(menu, actions, self.file_actions)
|
||||
return menu
|
||||
|
||||
def _create_edit_menu(self):
|
||||
"""创建编辑菜单"""
|
||||
# === Widget ===
|
||||
menu = QtWidgets.QMenu("编辑")
|
||||
|
||||
# === Actions ===
|
||||
self.edit_actions = {}
|
||||
actions = [
|
||||
("create_rl4", "创建 RL4 节点", "connect.png", ""),
|
||||
("delete_rl4", "删除 RL4 节点", "disconnect.png", ""),
|
||||
None,
|
||||
("mirror_l2r", "镜像左至右", "mirrorL.png", ""),
|
||||
("mirror_r2l", "镜像右至左", "mirrorR.png", ""),
|
||||
None,
|
||||
("pose_a2t", "姿势由 A 型转 T 型", "pose_A_To_T.png", ""),
|
||||
("pose_t2a", "姿势由 T 型转 A 型", "pose_T_To_A.png", ""),
|
||||
None,
|
||||
("transfer_lod", "传输 LOD 贴图", "locator.png", ""),
|
||||
("set_joint_color", "设置关节颜色", "color.png", ""),
|
||||
None,
|
||||
("unmark_all", "取消全部标记", "unmark_all.png", ""),
|
||||
("rebuild_targets", "重建所有目标", "rebuildTargets.png", ""),
|
||||
None,
|
||||
("set_expression_keys", "为所有表情设置关键帧", "bakeAnimation.png", ""),
|
||||
("bake_expression_keys", "烘焙所有表情的关键帧", "centerCurrentTime.png", "")
|
||||
]
|
||||
|
||||
self._add_menu_actions(menu, actions, self.edit_actions)
|
||||
return menu
|
||||
|
||||
def _create_tools_menu(self):
|
||||
"""创建工具菜单"""
|
||||
# === Widget ===
|
||||
menu = QtWidgets.QMenu("工具")
|
||||
|
||||
# === Actions ===
|
||||
self.tools_actions = {}
|
||||
actions = [
|
||||
("export_skin", "导出蒙皮", "export_skin.png", ""),
|
||||
("import_skin", "导入蒙皮", "import_skin.png", ""),
|
||||
("copy_skin", "拷贝装皮", "copy_skin.png", ""),
|
||||
None,
|
||||
("rbf_deformer", "RBF变形器", "blendShape.png", ""),
|
||||
("quick_bind", "快速绑定服装", "clothing_weight.png", ""),
|
||||
("clone_blend", "克隆混合变形", "blendShape.png", ""),
|
||||
None,
|
||||
("transfer_uv", "UV传递点序", "repair_vertex_order.png", ""),
|
||||
("create_face_ctrl", "面部生成控制器", "controller.png", ""),
|
||||
("extract_52bs", "提取52BS", "ARKit52.png", ""),
|
||||
None,
|
||||
("fix_joint_axis", "关节轴向修复", "joint.png", ""),
|
||||
("create_body_ctrl", "生成身体控制器", "create_body_ctrl.png", ""),
|
||||
None,
|
||||
("import_face_anim", "导入面部动画", "import_face_anim.png", ""),
|
||||
("import_body_anim", "导入身体动画", "import_body_anim.png", "")
|
||||
]
|
||||
|
||||
self._add_menu_actions(menu, actions, self.tools_actions)
|
||||
return menu
|
||||
|
||||
def _create_language_menu(self):
|
||||
"""创建语言菜单"""
|
||||
# === Widget ===
|
||||
menu = QtWidgets.QMenu("语言")
|
||||
|
||||
# === Actions ===
|
||||
self.language_actions = {}
|
||||
actions = [
|
||||
("chinese", "中文", "chinese.png", ""),
|
||||
("english", "English", "english.png", "")
|
||||
]
|
||||
|
||||
self._add_menu_actions(menu, actions, self.language_actions)
|
||||
return menu
|
||||
|
||||
def _create_help_menu(self):
|
||||
"""创建帮助菜单"""
|
||||
# === Widget ===
|
||||
menu = QtWidgets.QMenu("帮助")
|
||||
|
||||
# === Actions ===
|
||||
self.help_actions = {}
|
||||
actions = [
|
||||
("check_update", "检查更新", "update.png", ""),
|
||||
("help", "帮助文档", "help.png", "F1"),
|
||||
("about", "关于", "about.png", "")
|
||||
]
|
||||
|
||||
self._add_menu_actions(menu, actions, self.help_actions)
|
||||
return menu
|
||||
|
||||
def _add_menu_actions(self, menu, actions, action_dict):
|
||||
"""添加菜单项"""
|
||||
for action in actions:
|
||||
if action is None:
|
||||
menu.addSeparator()
|
||||
else:
|
||||
action_id, name, icon, shortcut = action
|
||||
act = QtWidgets.QAction(name, self)
|
||||
|
||||
if icon:
|
||||
act.setIcon(QtGui.QIcon(f"{config.ICONS_PATH}/{icon}"))
|
||||
|
||||
if shortcut:
|
||||
act.setShortcut(shortcut)
|
||||
|
||||
menu.addAction(act)
|
||||
action_dict[action_id] = act
|
||||
|
||||
def _create_connections(self):
|
||||
"""创建信号连接"""
|
||||
# 文件菜单
|
||||
self.file_actions["open_dna"].triggered.connect(self._on_open_dna)
|
||||
self.file_actions["save_dna"].triggered.connect(self._on_save_dna)
|
||||
self.file_actions["exit"].triggered.connect(self._on_exit)
|
||||
|
||||
# 编辑菜单
|
||||
self.edit_actions["create_rl4"].triggered.connect(self._on_create_rl4)
|
||||
self.edit_actions["delete_rl4"].triggered.connect(self._on_delete_rl4)
|
||||
|
||||
# 工具菜单
|
||||
self.tools_actions["export_skin"].triggered.connect(self._on_export_skin)
|
||||
self.tools_actions["import_skin"].triggered.connect(self._on_import_skin)
|
||||
|
||||
# 语言菜单
|
||||
self.language_actions["chinese"].triggered.connect(lambda: self._on_language_change("zh"))
|
||||
self.language_actions["english"].triggered.connect(lambda: self._on_language_change("en"))
|
||||
|
||||
# 帮助菜单
|
||||
self.help_actions["help"].triggered.connect(self._on_help)
|
||||
self.help_actions["about"].triggered.connect(self._on_about)
|
||||
|
||||
# ================================ 事件函数 ================================
|
||||
def _on_open_dna(self):
|
||||
"""打开DNA"""
|
||||
# TODO: 实现打开DNA逻辑
|
||||
pass
|
||||
|
||||
def _on_save_dna(self):
|
||||
"""保存DNA"""
|
||||
# TODO: 实现保存DNA逻辑
|
||||
pass
|
||||
|
||||
def _on_exit(self):
|
||||
"""退出程序"""
|
||||
# TODO: 实现退出逻辑
|
||||
pass
|
||||
|
||||
def _on_create_rl4(self):
|
||||
"""创建RL4节点"""
|
||||
# TODO: 实现创建RL4节点逻辑
|
||||
pass
|
||||
|
||||
def _on_delete_rl4(self):
|
||||
"""删除RL4节点"""
|
||||
# TODO: 实现删除RL4节点逻辑
|
||||
pass
|
||||
|
||||
def _on_export_skin(self):
|
||||
"""导出蒙皮"""
|
||||
# TODO: 实现导出蒙皮逻辑
|
||||
pass
|
||||
|
||||
def _on_import_skin(self):
|
||||
"""导入蒙皮"""
|
||||
# TODO: 实现导入蒙皮逻辑
|
||||
pass
|
||||
|
||||
def _on_language_change(self, lang):
|
||||
"""切换语言"""
|
||||
# TODO: 实现语言切换逻辑
|
||||
pass
|
||||
|
||||
def _on_help(self):
|
||||
"""显示帮助文档"""
|
||||
# TODO: 实现显示帮助逻辑
|
||||
pass
|
||||
|
||||
def _on_about(self):
|
||||
"""显示关于对话框"""
|
||||
# TODO: 实现显示关于对话框逻辑
|
||||
pass
|
||||
|
||||
if __name__ == "__main__":
|
||||
pass
|
@ -32,6 +32,220 @@ except ImportError:
|
||||
wrapInstance = None
|
||||
|
||||
class MeshesTab(QtWidgets.QWidget):
|
||||
def __init__(self, parent=None):
|
||||
super(MeshesTab, 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(2, 2, 2, 2)
|
||||
self.main_layout.setSpacing(2)
|
||||
|
||||
# 创建各个部件
|
||||
self.toolbar_widget = self._create_toolbar()
|
||||
self.lod_tab_widget = self._create_lod_tabs()
|
||||
self.bottom_toolbar_widget = self._create_bottom_toolbar()
|
||||
|
||||
# 添加到主布局
|
||||
self.main_layout.addWidget(self.toolbar_widget)
|
||||
self.main_layout.addWidget(self.lod_tab_widget)
|
||||
self.main_layout.addWidget(self.bottom_toolbar_widget)
|
||||
|
||||
def _create_toolbar(self):
|
||||
"""创建顶部工具栏"""
|
||||
# === Widget ===
|
||||
widget = QtWidgets.QWidget()
|
||||
|
||||
# === Layout ===
|
||||
layout = QtWidgets.QHBoxLayout(widget)
|
||||
layout.setContentsMargins(2, 2, 2, 2)
|
||||
layout.setSpacing(2)
|
||||
|
||||
# 预设下拉框
|
||||
self.preset_combo = QtWidgets.QComboBox()
|
||||
self.preset_combo.addItem("MetaHuman")
|
||||
layout.addWidget(self.preset_combo)
|
||||
|
||||
# 垃圾桶按钮
|
||||
self.trash_btn = QtWidgets.QPushButton()
|
||||
self.trash_btn.setIcon(QtGui.QIcon(f"{config.ICONS_PATH}/trash.png"))
|
||||
self.trash_btn.setFixedSize(24, 24)
|
||||
layout.addWidget(self.trash_btn)
|
||||
|
||||
layout.addStretch()
|
||||
|
||||
return widget
|
||||
|
||||
def _create_lod_tabs(self):
|
||||
"""创建LOD选项卡"""
|
||||
# === Widget ===
|
||||
self.lod_tab = QtWidgets.QTabWidget()
|
||||
|
||||
# 添加LOD页面
|
||||
for i in range(8):
|
||||
lod_widget = self._create_lod_page(i)
|
||||
self.lod_tab.addTab(lod_widget, f"LOD{i}")
|
||||
|
||||
return self.lod_tab
|
||||
|
||||
def _create_lod_page(self, lod_index):
|
||||
"""创建单个LOD页面"""
|
||||
# === Widget ===
|
||||
widget = QtWidgets.QWidget()
|
||||
|
||||
# === Layout ===
|
||||
layout = QtWidgets.QVBoxLayout(widget)
|
||||
layout.setContentsMargins(5, 5, 5, 5)
|
||||
layout.setSpacing(2)
|
||||
|
||||
# 创建网格列表
|
||||
scroll_area = QtWidgets.QScrollArea()
|
||||
scroll_area.setWidgetResizable(True)
|
||||
scroll_widget = QtWidgets.QWidget()
|
||||
scroll_layout = QtWidgets.QVBoxLayout(scroll_widget)
|
||||
|
||||
# 获取当前LOD级别的网格列表
|
||||
meshes = config.LOD_MESHES[f"LOD{lod_index}"]
|
||||
self.mesh_items = [] # 存储所有mesh item的引用
|
||||
|
||||
for mesh in meshes:
|
||||
mesh_item = self._create_mesh_item(mesh)
|
||||
scroll_layout.addWidget(mesh_item)
|
||||
self.mesh_items.append(mesh_item)
|
||||
|
||||
scroll_layout.addStretch()
|
||||
scroll_area.setWidget(scroll_widget)
|
||||
layout.addWidget(scroll_area)
|
||||
|
||||
# 添加底部按钮
|
||||
button_widget = QtWidgets.QWidget()
|
||||
button_layout = QtWidgets.QHBoxLayout(button_widget)
|
||||
button_layout.setContentsMargins(0, 0, 0, 0)
|
||||
|
||||
self.auto_select_btn = QtWidgets.QPushButton("自动选择模型")
|
||||
self.standardize_btn = QtWidgets.QPushButton("标准化命名")
|
||||
self.auto_group_btn = QtWidgets.QPushButton("自动分组")
|
||||
|
||||
button_layout.addWidget(self.auto_select_btn)
|
||||
button_layout.addWidget(self.standardize_btn)
|
||||
button_layout.addWidget(self.auto_group_btn)
|
||||
|
||||
layout.addWidget(button_widget)
|
||||
|
||||
return widget
|
||||
|
||||
def _create_mesh_item(self, mesh_name):
|
||||
"""创建单个网格项"""
|
||||
# === Widget ===
|
||||
widget = QtWidgets.QWidget()
|
||||
|
||||
# === Layout ===
|
||||
layout = QtWidgets.QHBoxLayout(widget)
|
||||
layout.setContentsMargins(0, 0, 0, 0)
|
||||
layout.setSpacing(2)
|
||||
|
||||
# 网格名称标签
|
||||
label = QtWidgets.QLabel(mesh_name)
|
||||
label.setFixedWidth(80)
|
||||
layout.addWidget(label)
|
||||
|
||||
# 网格路径输入框
|
||||
path_edit = QtWidgets.QLineEdit()
|
||||
layout.addWidget(path_edit)
|
||||
|
||||
# 添加按钮
|
||||
add_btn = QtWidgets.QPushButton("添加...")
|
||||
add_btn.setFixedWidth(60)
|
||||
layout.addWidget(add_btn)
|
||||
|
||||
return widget
|
||||
|
||||
def _create_bottom_toolbar(self):
|
||||
"""创建底部工具栏"""
|
||||
# === Widget ===
|
||||
widget = QtWidgets.QWidget()
|
||||
|
||||
# === Layout ===
|
||||
layout = QtWidgets.QHBoxLayout(widget)
|
||||
layout.setContentsMargins(5, 5, 5, 5)
|
||||
layout.setSpacing(5)
|
||||
|
||||
# 预设选择
|
||||
preset_label = QtWidgets.QLabel("预设:")
|
||||
self.preset_combo_bottom = QtWidgets.QComboBox()
|
||||
self.preset_combo_bottom.addItem("MetaHuman")
|
||||
|
||||
# LOD选择
|
||||
lod_label = QtWidgets.QLabel("选择LOD:")
|
||||
self.lod_combo = QtWidgets.QComboBox()
|
||||
self.lod_combo.addItem("全部")
|
||||
|
||||
# 功能按钮
|
||||
self.create_lod_btn = QtWidgets.QPushButton("生成当前LOD")
|
||||
self.modify_btn = QtWidgets.QPushButton("修复线性")
|
||||
self.save_btn = QtWidgets.QPushButton("修复存储")
|
||||
|
||||
# 添加到布局
|
||||
layout.addWidget(preset_label)
|
||||
layout.addWidget(self.preset_combo_bottom)
|
||||
layout.addStretch()
|
||||
layout.addWidget(lod_label)
|
||||
layout.addWidget(self.lod_combo)
|
||||
layout.addWidget(self.create_lod_btn)
|
||||
layout.addWidget(self.modify_btn)
|
||||
layout.addWidget(self.save_btn)
|
||||
|
||||
return widget
|
||||
|
||||
def _create_connections(self):
|
||||
"""创建信号连接"""
|
||||
# 顶部工具栏
|
||||
self.trash_btn.clicked.connect(self._on_trash_clicked)
|
||||
self.preset_combo.currentIndexChanged.connect(self._on_preset_changed)
|
||||
|
||||
# LOD页面按钮
|
||||
for i in range(self.lod_tab.count()):
|
||||
page = self.lod_tab.widget(i)
|
||||
auto_select_btn = page.findChild(QtWidgets.QPushButton, "自动选择模型")
|
||||
if auto_select_btn:
|
||||
auto_select_btn.clicked.connect(self._on_auto_select)
|
||||
|
||||
# 底部工具栏
|
||||
self.create_lod_btn.clicked.connect(self._on_create_lod)
|
||||
self.modify_btn.clicked.connect(self._on_modify)
|
||||
self.save_btn.clicked.connect(self._on_save)
|
||||
|
||||
def _on_trash_clicked(self):
|
||||
"""垃圾桶按钮点击"""
|
||||
# TODO: 实现清除功能
|
||||
pass
|
||||
|
||||
def _on_preset_changed(self, index):
|
||||
"""预设改变"""
|
||||
# TODO: 实现预设切换
|
||||
pass
|
||||
|
||||
def _on_auto_select(self):
|
||||
"""自动选择模型"""
|
||||
# TODO: 实现自动选择
|
||||
pass
|
||||
|
||||
def _on_create_lod(self):
|
||||
"""生成当前LOD"""
|
||||
# TODO: 实现LOD生成
|
||||
pass
|
||||
|
||||
def _on_modify(self):
|
||||
"""修复线性"""
|
||||
# TODO: 实现修复
|
||||
pass
|
||||
|
||||
def _on_save(self):
|
||||
"""修复存储"""
|
||||
# TODO: 实现存储
|
||||
pass
|
||||
|
||||
|
||||
|
@ -32,8 +32,235 @@ except ImportError:
|
||||
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.QHBoxLayout(self)
|
||||
self.main_layout.setContentsMargins(2, 2, 2, 2)
|
||||
self.main_layout.setSpacing(2)
|
||||
|
||||
# 创建左右两个主面板
|
||||
self.dna_browser_widget = self._create_dna_browser()
|
||||
self.asset_settings_widget = self._create_asset_settings()
|
||||
|
||||
# 设置左右比例为1:1
|
||||
self.main_layout.addWidget(self.dna_browser_widget, 1)
|
||||
self.main_layout.addWidget(self.asset_settings_widget, 1)
|
||||
|
||||
def _create_dna_browser(self):
|
||||
"""创建DNA预设浏览器"""
|
||||
# === Widget ===
|
||||
widget = QtWidgets.QWidget()
|
||||
|
||||
# === Layout ===
|
||||
layout = QtWidgets.QVBoxLayout(widget)
|
||||
layout.setContentsMargins(5, 5, 5, 5)
|
||||
layout.setSpacing(5)
|
||||
|
||||
# 预设网格视图
|
||||
self.preset_view = QtWidgets.QListWidget()
|
||||
self.preset_view.setViewMode(QtWidgets.QListView.IconMode)
|
||||
self.preset_view.setIconSize(QtCore.QSize(90, 90))
|
||||
self.preset_view.setSpacing(10)
|
||||
self.preset_view.setResizeMode(QtWidgets.QListView.Adjust)
|
||||
self.preset_view.setMovement(QtWidgets.QListView.Static)
|
||||
self.preset_view.setWrapping(True)
|
||||
layout.addWidget(self.preset_view)
|
||||
|
||||
# 缩放控制
|
||||
zoom_widget = QtWidgets.QWidget()
|
||||
zoom_layout = QtWidgets.QHBoxLayout(zoom_widget)
|
||||
zoom_layout.setContentsMargins(0, 0, 0, 0)
|
||||
|
||||
zoom_label = QtWidgets.QLabel("缩放:")
|
||||
self.zoom_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal)
|
||||
self.zoom_slider.setMinimum(60)
|
||||
self.zoom_slider.setMaximum(200)
|
||||
self.zoom_slider.setValue(90)
|
||||
self.zoom_value_label = QtWidgets.QLabel("90")
|
||||
|
||||
zoom_layout.addWidget(zoom_label)
|
||||
zoom_layout.addWidget(self.zoom_slider)
|
||||
zoom_layout.addWidget(self.zoom_value_label)
|
||||
layout.addWidget(zoom_widget)
|
||||
|
||||
# 导入/导出按钮
|
||||
button_widget = QtWidgets.QWidget()
|
||||
button_layout = QtWidgets.QHBoxLayout(button_widget)
|
||||
button_layout.setContentsMargins(0, 0, 0, 0)
|
||||
|
||||
self.import_btn = QtWidgets.QPushButton("导入设置")
|
||||
self.export_btn = QtWidgets.QPushButton("导出设置")
|
||||
|
||||
button_layout.addWidget(self.import_btn)
|
||||
button_layout.addWidget(self.export_btn)
|
||||
layout.addWidget(button_widget)
|
||||
|
||||
return widget
|
||||
|
||||
def _create_asset_settings(self):
|
||||
"""创建资产设置面板"""
|
||||
# === Widget ===
|
||||
widget = QtWidgets.QWidget()
|
||||
|
||||
# === Layout ===
|
||||
layout = QtWidgets.QVBoxLayout(widget)
|
||||
layout.setContentsMargins(5, 5, 5, 5)
|
||||
layout.setSpacing(5)
|
||||
|
||||
# 项目路径设置
|
||||
self.project_group = self._create_project_settings()
|
||||
layout.addWidget(self.project_group)
|
||||
|
||||
# 数据分层选项
|
||||
self.layer_group = self._create_layer_settings()
|
||||
layout.addWidget(self.layer_group)
|
||||
|
||||
# 描述设置
|
||||
self.desc_group = self._create_description_settings()
|
||||
layout.addWidget(self.desc_group)
|
||||
|
||||
layout.addStretch()
|
||||
|
||||
return widget
|
||||
|
||||
def _create_project_settings(self):
|
||||
"""创建项目设置组"""
|
||||
# === Widget ===
|
||||
group = QtWidgets.QGroupBox("项目设置")
|
||||
|
||||
# === Layout ===
|
||||
layout = QtWidgets.QFormLayout(group)
|
||||
layout.setContentsMargins(5, 5, 5, 5)
|
||||
layout.setSpacing(5)
|
||||
|
||||
# 项目路径
|
||||
path_widget = QtWidgets.QWidget()
|
||||
path_layout = QtWidgets.QHBoxLayout(path_widget)
|
||||
path_layout.setContentsMargins(0, 0, 0, 0)
|
||||
|
||||
self.project_path = QtWidgets.QLineEdit()
|
||||
self.browse_project_btn = QtWidgets.QPushButton("浏览...")
|
||||
self.browse_project_btn.setFixedWidth(60)
|
||||
|
||||
path_layout.addWidget(self.project_path)
|
||||
path_layout.addWidget(self.browse_project_btn)
|
||||
layout.addRow("项目路径:", path_widget)
|
||||
|
||||
# 预设文件
|
||||
preset_widget = QtWidgets.QWidget()
|
||||
preset_layout = QtWidgets.QHBoxLayout(preset_widget)
|
||||
preset_layout.setContentsMargins(0, 0, 0, 0)
|
||||
|
||||
self.preset_path = QtWidgets.QLineEdit()
|
||||
self.browse_preset_btn = QtWidgets.QPushButton("浏览...")
|
||||
self.browse_preset_btn.setFixedWidth(60)
|
||||
|
||||
preset_layout.addWidget(self.preset_path)
|
||||
preset_layout.addWidget(self.browse_preset_btn)
|
||||
layout.addRow("预设文件:", preset_widget)
|
||||
|
||||
return group
|
||||
|
||||
def _create_layer_settings(self):
|
||||
"""创建数据分层设置组"""
|
||||
# === Widget ===
|
||||
group = QtWidgets.QGroupBox("数据分层")
|
||||
|
||||
# === Layout ===
|
||||
layout = QtWidgets.QVBoxLayout(group)
|
||||
layout.setContentsMargins(5, 5, 5, 5)
|
||||
layout.setSpacing(5)
|
||||
|
||||
self.behavior_check = QtWidgets.QCheckBox("行为(包括描述和定义)")
|
||||
self.expression_check = QtWidgets.QCheckBox("覆盖表情选项")
|
||||
|
||||
layout.addWidget(self.behavior_check)
|
||||
layout.addWidget(self.expression_check)
|
||||
|
||||
return group
|
||||
|
||||
def _create_description_settings(self):
|
||||
"""创建描述设置组"""
|
||||
# === Widget ===
|
||||
group = QtWidgets.QGroupBox("描述设置")
|
||||
|
||||
# === Layout ===
|
||||
layout = QtWidgets.QFormLayout(group)
|
||||
layout.setContentsMargins(5, 5, 5, 5)
|
||||
layout.setSpacing(5)
|
||||
|
||||
# 创建设置项
|
||||
self.name_edit = QtWidgets.QLineEdit("Archetype")
|
||||
self.type_combo = QtWidgets.QComboBox()
|
||||
self.type_combo.addItem("其他")
|
||||
self.gender_combo = QtWidgets.QComboBox()
|
||||
self.gender_combo.addItem("女性")
|
||||
self.age_spin = QtWidgets.QSpinBox()
|
||||
self.age_spin.setValue(24)
|
||||
self.transform_combo = QtWidgets.QComboBox()
|
||||
self.transform_combo.addItem("厘米")
|
||||
self.rotation_combo = QtWidgets.QComboBox()
|
||||
self.rotation_combo.addItem("角度")
|
||||
self.up_axis_combo = QtWidgets.QComboBox()
|
||||
self.up_axis_combo.addItem("Z轴向上")
|
||||
self.lod_spin = QtWidgets.QSpinBox()
|
||||
self.lod_spin.setValue(8)
|
||||
|
||||
# 添加到布局
|
||||
layout.addRow("名称:", self.name_edit)
|
||||
layout.addRow("原型:", self.type_combo)
|
||||
layout.addRow("性别:", self.gender_combo)
|
||||
layout.addRow("年龄:", self.age_spin)
|
||||
layout.addRow("变换单位:", self.transform_combo)
|
||||
layout.addRow("旋转单位:", self.rotation_combo)
|
||||
layout.addRow("向上轴标:", self.up_axis_combo)
|
||||
layout.addRow("LOD计数:", self.lod_spin)
|
||||
|
||||
return group
|
||||
|
||||
def _create_connections(self):
|
||||
"""创建信号连接"""
|
||||
# 缩放滑块
|
||||
self.zoom_slider.valueChanged.connect(self._on_zoom_changed)
|
||||
|
||||
# 导入导出按钮
|
||||
self.import_btn.clicked.connect(self._on_import)
|
||||
self.export_btn.clicked.connect(self._on_export)
|
||||
|
||||
# 浏览按钮
|
||||
self.browse_project_btn.clicked.connect(self._on_browse_project)
|
||||
self.browse_preset_btn.clicked.connect(self._on_browse_preset)
|
||||
|
||||
def _on_zoom_changed(self, value):
|
||||
"""缩放值改变"""
|
||||
self.zoom_value_label.setText(str(value))
|
||||
self.preset_view.setIconSize(QtCore.QSize(value, value))
|
||||
|
||||
def _on_import(self):
|
||||
"""导入设置"""
|
||||
# TODO: 实现导入逻辑
|
||||
pass
|
||||
|
||||
def _on_export(self):
|
||||
"""导出设置"""
|
||||
# TODO: 实现导出逻辑
|
||||
pass
|
||||
|
||||
def _on_browse_project(self):
|
||||
"""浏览项目路径"""
|
||||
# TODO: 实现浏览逻辑
|
||||
pass
|
||||
|
||||
def _on_browse_preset(self):
|
||||
"""浏览预设文件"""
|
||||
# TODO: 实现浏览逻辑
|
||||
pass
|
||||
|
||||
if __name__ == "__main__":
|
||||
pass
|
139
scripts/ui/toolshelf.py
Normal file
139
scripts/ui/toolshelf.py
Normal file
@ -0,0 +1,139 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from PySide2 import QtCore, QtGui, QtWidgets
|
||||
from scripts import config
|
||||
|
||||
class ToolShelf(QtWidgets.QWidget):
|
||||
def __init__(self, parent=None):
|
||||
super(ToolShelf, self).__init__(parent)
|
||||
self._setup_ui()
|
||||
self._create_connections()
|
||||
|
||||
def _setup_ui(self):
|
||||
"""设置UI布局"""
|
||||
# === Main Layout ===
|
||||
self.main_layout = QtWidgets.QHBoxLayout(self)
|
||||
self.main_layout.setContentsMargins(2, 2, 2, 2)
|
||||
self.main_layout.setSpacing(4)
|
||||
|
||||
# 创建工具按钮
|
||||
self.tool_buttons = {}
|
||||
self._create_tool_buttons()
|
||||
|
||||
def _create_tool_buttons(self):
|
||||
"""创建工具按钮"""
|
||||
# === 工具按钮配置 ===
|
||||
tools = [
|
||||
("save_dna", "保存 DNA", "save.png"),
|
||||
("load_dna", "加载当前项目 DNA", "open.png"),
|
||||
None, # 分隔符
|
||||
("create_rl4", "创建RL4节点", "connect.png"),
|
||||
("delete_rl4", "删除RL4节点", "disconnect.png"),
|
||||
None,
|
||||
("export_skin", "导出蒙皮", "export_skin.png"),
|
||||
("import_skin", "导入蒙皮", "import_skin.png"),
|
||||
("copy_skin", "复制蒙皮", "copy_skin.png"),
|
||||
None,
|
||||
("help", "帮助文档", "help.png"),
|
||||
("about", "关于", "about.png")
|
||||
]
|
||||
|
||||
# === 创建按钮 ===
|
||||
for tool in tools:
|
||||
if tool is None:
|
||||
# 添加分隔符
|
||||
separator = QtWidgets.QFrame()
|
||||
separator.setFrameShape(QtWidgets.QFrame.VLine)
|
||||
separator.setFrameShadow(QtWidgets.QFrame.Sunken)
|
||||
self.main_layout.addWidget(separator)
|
||||
else:
|
||||
tool_id, name, icon = tool
|
||||
button = self._create_tool_button(name, icon)
|
||||
self.tool_buttons[tool_id] = button
|
||||
self.main_layout.addWidget(button)
|
||||
|
||||
# 添加弹性空间
|
||||
self.main_layout.addStretch()
|
||||
|
||||
def _create_tool_button(self, name, icon):
|
||||
"""创建单个工具按钮"""
|
||||
# === Widget ===
|
||||
button = QtWidgets.QToolButton()
|
||||
|
||||
# === 设置按钮属性 ===
|
||||
button.setIcon(QtGui.QIcon(f"{config.ICONS_PATH}/{icon}"))
|
||||
button.setIconSize(QtCore.QSize(24, 24))
|
||||
button.setToolTip(name)
|
||||
button.setStatusTip(name)
|
||||
|
||||
# 设置按钮样式
|
||||
button.setToolButtonStyle(QtCore.Qt.ToolButtonIconOnly)
|
||||
button.setAutoRaise(True) # 鼠标悬停时才显示边框
|
||||
|
||||
return button
|
||||
|
||||
def _create_connections(self):
|
||||
"""创建信号连接"""
|
||||
# 保存/加载DNA
|
||||
self.tool_buttons["save_dna"].clicked.connect(self._on_save_dna)
|
||||
self.tool_buttons["load_dna"].clicked.connect(self._on_load_dna)
|
||||
|
||||
# RL4节点
|
||||
self.tool_buttons["create_rl4"].clicked.connect(self._on_create_rl4)
|
||||
self.tool_buttons["delete_rl4"].clicked.connect(self._on_delete_rl4)
|
||||
|
||||
# 蒙皮操作
|
||||
self.tool_buttons["export_skin"].clicked.connect(self._on_export_skin)
|
||||
self.tool_buttons["import_skin"].clicked.connect(self._on_import_skin)
|
||||
self.tool_buttons["copy_skin"].clicked.connect(self._on_copy_skin)
|
||||
|
||||
# 帮助/关于
|
||||
self.tool_buttons["help"].clicked.connect(self._on_help)
|
||||
self.tool_buttons["about"].clicked.connect(self._on_about)
|
||||
|
||||
# ================================ 事件函数 ================================
|
||||
def _on_save_dna(self):
|
||||
"""保存DNA"""
|
||||
# TODO: 实现保存DNA逻辑
|
||||
pass
|
||||
|
||||
def _on_load_dna(self):
|
||||
"""加载DNA"""
|
||||
# TODO: 实现加载DNA逻辑
|
||||
pass
|
||||
|
||||
def _on_create_rl4(self):
|
||||
"""创建RL4节点"""
|
||||
# TODO: 实现创建RL4节点逻辑
|
||||
pass
|
||||
|
||||
def _on_delete_rl4(self):
|
||||
"""删除RL4节点"""
|
||||
# TODO: 实现删除RL4节点逻辑
|
||||
pass
|
||||
|
||||
def _on_export_skin(self):
|
||||
"""导出蒙皮"""
|
||||
# TODO: 实现导出蒙皮逻辑
|
||||
pass
|
||||
|
||||
def _on_import_skin(self):
|
||||
"""导入蒙皮"""
|
||||
# TODO: 实现导入蒙皮逻辑
|
||||
pass
|
||||
|
||||
def _on_copy_skin(self):
|
||||
"""复制蒙皮"""
|
||||
# TODO: 实现复制蒙皮逻辑
|
||||
pass
|
||||
|
||||
def _on_help(self):
|
||||
"""显示帮助文档"""
|
||||
# TODO: 实现显示帮助逻辑
|
||||
pass
|
||||
|
||||
def _on_about(self):
|
||||
"""显示关于对话框"""
|
||||
# TODO: 实现显示关于对话框逻辑
|
||||
pass
|
@ -9,3 +9,209 @@ import maya.mel as mel
|
||||
import webbrowser
|
||||
import sys
|
||||
import os
|
||||
from PySide2 import QtCore, QtGui, QtWidgets
|
||||
|
||||
class ToolShelf(QtWidgets.QToolBar):
|
||||
def __init__(self, parent=None):
|
||||
super(ToolShelf, self).__init__(parent)
|
||||
self.setIconSize(QtCore.QSize(24, 24))
|
||||
self.setToolButtonStyle(QtCore.Qt.ToolButtonIconOnly)
|
||||
|
||||
# 添加工具按钮
|
||||
self._add_tools()
|
||||
|
||||
def _add_tools(self):
|
||||
"""添加工具按钮"""
|
||||
tools = [
|
||||
("保存 DNA", "save.png"),
|
||||
("加载当前项目 DNA", "open.png"),
|
||||
None, # 分隔符
|
||||
("创建RL4节点", "connect.png"),
|
||||
("删除RL4节点", "disconnect.png"),
|
||||
None,
|
||||
("导出蒙皮", "export_skin.png"),
|
||||
("导入蒙皮", "import_skin.png"),
|
||||
("复制蒙皮", "copy_skin.png"),
|
||||
None,
|
||||
("帮助文档", "help.png"),
|
||||
("关于", "about.png")
|
||||
]
|
||||
|
||||
for tool in tools:
|
||||
if tool is None:
|
||||
self.addSeparator()
|
||||
else:
|
||||
name, icon = tool
|
||||
action = QtWidgets.QAction(QtGui.QIcon(f"{config.ICONS_PATH}/{icon}"), name, self)
|
||||
self.addAction(action)
|
||||
|
||||
class IconButton(QtWidgets.QPushButton):
|
||||
"""带图标的按钮"""
|
||||
def __init__(self, icon_name, tooltip="", size=24, parent=None):
|
||||
super(IconButton, self).__init__(parent)
|
||||
self._setup_ui(icon_name, tooltip, size)
|
||||
|
||||
def _setup_ui(self, icon_name, tooltip, size):
|
||||
# 设置图标
|
||||
icon = QtGui.QIcon(f"{config.ICONS_PATH}/{icon_name}")
|
||||
self.setIcon(icon)
|
||||
self.setIconSize(QtCore.QSize(size, size))
|
||||
|
||||
# 设置样式
|
||||
self.setFixedSize(size, size)
|
||||
self.setToolTip(tooltip)
|
||||
self.setStyleSheet("""
|
||||
QPushButton {
|
||||
border: none;
|
||||
background: transparent;
|
||||
}
|
||||
QPushButton:hover {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
QPushButton:pressed {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
""")
|
||||
|
||||
class SearchLineEdit(QtWidgets.QLineEdit):
|
||||
"""带搜索图标的输入框"""
|
||||
def __init__(self, parent=None):
|
||||
super(SearchLineEdit, self).__init__(parent)
|
||||
self._setup_ui()
|
||||
|
||||
def _setup_ui(self):
|
||||
# 设置样式
|
||||
self.setPlaceholderText("搜索...")
|
||||
|
||||
# 添加搜索图标
|
||||
search_action = QtWidgets.QAction(self)
|
||||
search_action.setIcon(QtGui.QIcon(f"{config.ICONS_PATH}/search.png"))
|
||||
self.addAction(search_action, QtWidgets.QLineEdit.LeadingPosition)
|
||||
|
||||
# 添加清除按钮
|
||||
self.setClearButtonEnabled(True)
|
||||
|
||||
class CollapsibleWidget(QtWidgets.QWidget):
|
||||
"""可折叠的控件组"""
|
||||
def __init__(self, title="", parent=None):
|
||||
super(CollapsibleWidget, self).__init__(parent)
|
||||
self._setup_ui(title)
|
||||
self._create_connections()
|
||||
|
||||
def _setup_ui(self, title):
|
||||
# === Main Layout ===
|
||||
self.main_layout = QtWidgets.QVBoxLayout(self)
|
||||
self.main_layout.setContentsMargins(0, 0, 0, 0)
|
||||
self.main_layout.setSpacing(0)
|
||||
|
||||
# === Header ===
|
||||
self.header_widget = QtWidgets.QWidget()
|
||||
header_layout = QtWidgets.QHBoxLayout(self.header_widget)
|
||||
header_layout.setContentsMargins(5, 5, 5, 5)
|
||||
|
||||
# 展开/折叠按钮
|
||||
self.toggle_btn = IconButton("arrow_down.png", size=16)
|
||||
header_layout.addWidget(self.toggle_btn)
|
||||
|
||||
# 标题
|
||||
title_label = QtWidgets.QLabel(title)
|
||||
header_layout.addWidget(title_label)
|
||||
header_layout.addStretch()
|
||||
|
||||
self.main_layout.addWidget(self.header_widget)
|
||||
|
||||
# === Content ===
|
||||
self.content_widget = QtWidgets.QWidget()
|
||||
self.content_layout = QtWidgets.QVBoxLayout(self.content_widget)
|
||||
self.content_layout.setContentsMargins(20, 5, 5, 5)
|
||||
|
||||
self.main_layout.addWidget(self.content_widget)
|
||||
|
||||
def _create_connections(self):
|
||||
self.toggle_btn.clicked.connect(self._toggle_content)
|
||||
|
||||
def _toggle_content(self):
|
||||
"""切换内容显示/隐藏"""
|
||||
if self.content_widget.isVisible():
|
||||
self.content_widget.hide()
|
||||
self.toggle_btn.setIcon(QtGui.QIcon(f"{config.ICONS_PATH}/arrow_right.png"))
|
||||
else:
|
||||
self.content_widget.show()
|
||||
self.toggle_btn.setIcon(QtGui.QIcon(f"{config.ICONS_PATH}/arrow_down.png"))
|
||||
|
||||
def add_widget(self, widget):
|
||||
"""添加控件到内容区域"""
|
||||
self.content_layout.addWidget(widget)
|
||||
|
||||
class LabeledSpinBox(QtWidgets.QWidget):
|
||||
"""带标签的数值输入框"""
|
||||
valueChanged = QtCore.Signal(float) # 值改变信号
|
||||
|
||||
def __init__(self, label="", min_value=0.0, max_value=1.0, decimals=3, parent=None):
|
||||
super(LabeledSpinBox, self).__init__(parent)
|
||||
self._setup_ui(label, min_value, max_value, decimals)
|
||||
self._create_connections()
|
||||
|
||||
def _setup_ui(self, label, min_value, max_value, decimals):
|
||||
# === Layout ===
|
||||
layout = QtWidgets.QHBoxLayout(self)
|
||||
layout.setContentsMargins(0, 0, 0, 0)
|
||||
|
||||
# 标签
|
||||
self.label = QtWidgets.QLabel(label)
|
||||
layout.addWidget(self.label)
|
||||
|
||||
# 数值输入框
|
||||
self.spin_box = QtWidgets.QDoubleSpinBox()
|
||||
self.spin_box.setMinimum(min_value)
|
||||
self.spin_box.setMaximum(max_value)
|
||||
self.spin_box.setDecimals(decimals)
|
||||
layout.addWidget(self.spin_box)
|
||||
|
||||
def _create_connections(self):
|
||||
self.spin_box.valueChanged.connect(self.valueChanged.emit)
|
||||
|
||||
def value(self):
|
||||
return self.spin_box.value()
|
||||
|
||||
def setValue(self, value):
|
||||
self.spin_box.setValue(value)
|
||||
|
||||
class StatusWidget(QtWidgets.QWidget):
|
||||
"""状态显示控件"""
|
||||
def __init__(self, parent=None):
|
||||
super(StatusWidget, self).__init__(parent)
|
||||
self._setup_ui()
|
||||
|
||||
def _setup_ui(self):
|
||||
# === Layout ===
|
||||
layout = QtWidgets.QHBoxLayout(self)
|
||||
layout.setContentsMargins(5, 2, 5, 2)
|
||||
|
||||
# 状态图标
|
||||
self.icon_label = QtWidgets.QLabel()
|
||||
self.icon_label.setFixedSize(16, 16)
|
||||
layout.addWidget(self.icon_label)
|
||||
|
||||
# 状态文本
|
||||
self.text_label = QtWidgets.QLabel()
|
||||
layout.addWidget(self.text_label)
|
||||
|
||||
layout.addStretch()
|
||||
|
||||
def set_status(self, status, message):
|
||||
"""设置状态
|
||||
status: 'normal', 'warning', 'error'
|
||||
"""
|
||||
icon_map = {
|
||||
'normal': 'status_normal.png',
|
||||
'warning': 'status_warning.png',
|
||||
'error': 'status_error.png'
|
||||
}
|
||||
|
||||
if status in icon_map:
|
||||
self.icon_label.setPixmap(
|
||||
QtGui.QPixmap(f"{config.ICONS_PATH}/{icon_map[status]}")
|
||||
)
|
||||
|
||||
self.text_label.setText(message)
|
||||
|
Loading…
Reference in New Issue
Block a user