Update
This commit is contained in:
385
scripts/Main.py
385
scripts/Main.py
@@ -5,7 +5,7 @@
|
||||
Main module for Metahuman customize plugin
|
||||
主模块 - 负责初始化UI和功能集成
|
||||
功能: 从ui模块加载子模块显示
|
||||
作者: Virtuos Games
|
||||
作者: CGNICO
|
||||
版本: Alpha v1.0.0
|
||||
"""
|
||||
#===================================== IMPORT MODULES =====================================
|
||||
@@ -23,261 +23,194 @@ import locale
|
||||
import sys
|
||||
import os
|
||||
#===================================== IMPORT UI MODULES ===================================
|
||||
from scripts.ui import ui_utils
|
||||
from scripts.ui import toolbar
|
||||
from scripts.ui import geometry
|
||||
from scripts.ui import rigging
|
||||
from scripts.ui import behaviour
|
||||
from scripts.ui import definition
|
||||
#====================================== LOCALIZATION ==================================
|
||||
#========================================= LOCALIZATION =====================================
|
||||
from scripts.ui import localization
|
||||
LANG = localization.LANG
|
||||
#========================================== CONFIG ========================================
|
||||
# 从 scripts 模块导入配置变量
|
||||
from scripts import (
|
||||
TOOL_NAME, TOOL_VERSION, TOOL_AUTHOR, TOOL_YEAR, TOOL_MOD_FILENAME,
|
||||
TOOL_LANG, TOOL_WSCL_NAME, TOOL_HELP_URL, TOOL_PATH, SCRIPTS_PATH,
|
||||
TOOL_MAIN_SCRIPT, UI_PATH, STYLE_FILE, ICONS_PATH, TOOL_ICON,
|
||||
ASSETS_PATH, DNA_FILE_PATH, DNA_IMG_PATH, TOOL_COMMAND_ICON
|
||||
)
|
||||
#========================================= INIT =======================================
|
||||
def get_system_encoding():
|
||||
encoding = sys.getdefaultencoding()
|
||||
if encoding.lower() == 'ascii':
|
||||
encoding = locale.getpreferredencoding()
|
||||
return encoding
|
||||
|
||||
def maya_main_window():
|
||||
main_window_ptr = omui.MQtUtil.mainWindow()
|
||||
return wrapInstance(int(main_window_ptr), QtWidgets.QWidget)
|
||||
#===================================== MAIN FUNCTION ===================================
|
||||
#=========================================== 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
|
||||
#======================================= MAIN FUNCTION =====================================
|
||||
class MainWindow(QtWidgets.QWidget):
|
||||
def __init__(self, parent=maya_main_window()):
|
||||
def __init__(self, parent=ui_utils.get_maya_main_window()):
|
||||
super(MainWindow, self).__init__(parent)
|
||||
self.setWindowTitle(TOOL_NAME)
|
||||
self.setObjectName(f"{TOOL_NAME}MainWindow")
|
||||
self.setWindowFlags(QtCore.Qt.Window)
|
||||
self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
|
||||
self.setMinimumSize(1200, 800)
|
||||
|
||||
# 设置自适应大小策略
|
||||
self.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
|
||||
self.setMinimumSize(300, 600) # 减小最小高度,让窗口更灵活
|
||||
# 设置窗口图标
|
||||
if os.path.exists(TOOL_ICON):
|
||||
self.setWindowIcon(QtGui.QIcon(TOOL_ICON))
|
||||
|
||||
# 加载样式表
|
||||
self.load_stylesheet()
|
||||
|
||||
# 初始化UI模块
|
||||
self.toolbar_ui = toolbar.ToolbarUI()
|
||||
self.definition_ui = definition.DefinitionUI()
|
||||
self.geometry_ui = geometry.GeometryUI()
|
||||
self.rigging_ui = rigging.RiggingUI()
|
||||
self.behaviour_ui = behaviour.BehaviourUI()
|
||||
|
||||
# 初始化UI组件
|
||||
self.create_widgets()
|
||||
self.create_layouts()
|
||||
self.create_connections()
|
||||
|
||||
# 不设置窗口图标
|
||||
|
||||
def dock_to_maya(self):
|
||||
if cmds.workspaceControl(TOOL_WSCL_NAME, exists=True):
|
||||
cmds.deleteUI(TOOL_WSCL_NAME)
|
||||
|
||||
def create_control():
|
||||
try:
|
||||
# 直接使用TOOL_ICON,__init__.py中已经检查了图标文件是否存在
|
||||
workspace_control = cmds.workspaceControl(
|
||||
TOOL_WSCL_NAME,
|
||||
label=TOOL_NAME,
|
||||
floating=True,
|
||||
retain=True,
|
||||
resizeWidth=True,
|
||||
initialWidth=600,
|
||||
minimumWidth=600
|
||||
)
|
||||
cmds.workspaceControl(TOOL_WSCL_NAME, e=True, resizeWidth=True)
|
||||
cmds.control(self.objectName(), e=True, p=workspace_control)
|
||||
|
||||
# 尝试设置工作区控件的尺寸和属性
|
||||
try:
|
||||
# 使用Maya命令设置工作区控件属性
|
||||
cmds.workspaceControl(TOOL_WSCL_NAME, e=True, widthProperty="preferred", heightProperty="preferred")
|
||||
|
||||
# 使用原始标题,不添加额外的图标字符
|
||||
cmds.workspaceControl(TOOL_WSCL_NAME, e=True, label=TOOL_NAME)
|
||||
except Exception as e:
|
||||
print(f"设置工作区控件属性失败: {e}")
|
||||
|
||||
cmds.evalDeferred(lambda: cmds.workspaceControl(TOOL_WSCL_NAME, e=True, resizeWidth=True))
|
||||
except Exception as e:
|
||||
print("Error creating workspace control: {}".format(e))
|
||||
|
||||
cmds.evalDeferred(create_control)
|
||||
#===================================== UI COMPONENTS =====================================
|
||||
def create_widgets(self):
|
||||
# 创建滚动区域
|
||||
self.scroll_area = QtWidgets.QScrollArea()
|
||||
self.scroll_area.setObjectName("main_scroll_area")
|
||||
self.scroll_area.setWidgetResizable(True)
|
||||
self.scroll_area.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
|
||||
self.scroll_area.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) # 改回按需显示
|
||||
self.scroll_area.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
|
||||
|
||||
# 创建滚动区域内容控件
|
||||
self.scroll_content = QtWidgets.QWidget()
|
||||
self.scroll_content.setObjectName("scroll_content")
|
||||
self.scroll_content.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
|
||||
|
||||
# 创建主标签页
|
||||
self.main_tab = QtWidgets.QTabWidget()
|
||||
self.main_tab.setObjectName("main_tab")
|
||||
self.main_tab.setTabPosition(QtWidgets.QTabWidget.North)
|
||||
self.main_tab.setTabShape(QtWidgets.QTabWidget.Rounded)
|
||||
self.main_tab.setDocumentMode(True)
|
||||
self.main_tab.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
|
||||
self.main_tab.setMinimumHeight(400)
|
||||
|
||||
# 创建各功能模块标签页
|
||||
self.geometry_tab = QtWidgets.QWidget()
|
||||
self.geometry_tab.setObjectName("geometry_tab")
|
||||
self.geometry_tab.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
|
||||
|
||||
self.rigging_tab = QtWidgets.QWidget()
|
||||
self.rigging_tab.setObjectName("rigging_tab")
|
||||
self.rigging_tab.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
|
||||
|
||||
self.behaviour_tab = QtWidgets.QWidget()
|
||||
self.behaviour_tab.setObjectName("behaviour_tab")
|
||||
self.behaviour_tab.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
|
||||
|
||||
self.definition_tab = QtWidgets.QWidget()
|
||||
self.definition_tab.setObjectName("definition_tab")
|
||||
self.definition_tab.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
|
||||
|
||||
# 创建工具栏
|
||||
self.toolbar_frame = QtWidgets.QFrame()
|
||||
self.toolbar_frame.setObjectName("toolbar_frame")
|
||||
self.toolbar_frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
|
||||
self.toolbar_frame.setFrameShadow(QtWidgets.QFrame.Raised)
|
||||
self.toolbar_frame.setMaximumHeight(40)
|
||||
self.toolbar_frame.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
|
||||
# 创建状态栏
|
||||
self.status_bar = QtWidgets.QStatusBar()
|
||||
self.status_bar.setObjectName("status_bar")
|
||||
self.status_bar.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
self.status_bar.showMessage(f"{TOOL_NAME} {TOOL_VERSION}")
|
||||
|
||||
# 初始化各模块UI组件
|
||||
toolbar.widgets()
|
||||
geometry.widgets()
|
||||
rigging.widgets()
|
||||
behaviour.widgets()
|
||||
definition.widgets()
|
||||
|
||||
def create_layouts(self):
|
||||
# 主布局
|
||||
self.main_layout = QtWidgets.QVBoxLayout(self)
|
||||
self.main_layout.setContentsMargins(2, 2, 2, 2)
|
||||
self.main_layout.setSpacing(2)
|
||||
|
||||
# 滚动区域内容布局
|
||||
self.scroll_content_layout = QtWidgets.QVBoxLayout(self.scroll_content)
|
||||
self.scroll_content_layout.setContentsMargins(2, 2, 2, 2)
|
||||
self.scroll_content_layout.setSpacing(2)
|
||||
|
||||
# 创建工具栏布局
|
||||
self.toolbar_layout = QtWidgets.QVBoxLayout(self.toolbar_frame)
|
||||
self.toolbar_layout.setContentsMargins(0, 0, 0, 0)
|
||||
|
||||
# 使用toolbar模块创建工具栏元素
|
||||
toolbar.layouts(parent_frame=self.toolbar_frame)
|
||||
|
||||
# 设置各标签页布局
|
||||
self.geometry_layout = QtWidgets.QVBoxLayout(self.geometry_tab)
|
||||
self.geometry_layout.setContentsMargins(4, 4, 4, 4)
|
||||
geometry.layouts(parent_tab=self.geometry_tab)
|
||||
|
||||
self.rigging_layout = QtWidgets.QVBoxLayout(self.rigging_tab)
|
||||
self.rigging_layout.setContentsMargins(4, 4, 4, 4)
|
||||
rigging.layouts(parent_tab=self.rigging_tab)
|
||||
|
||||
self.behaviour_layout = QtWidgets.QVBoxLayout(self.behaviour_tab)
|
||||
self.behaviour_layout.setContentsMargins(4, 4, 4, 4)
|
||||
behaviour.layouts(parent_tab=self.behaviour_tab)
|
||||
|
||||
self.definition_layout = QtWidgets.QVBoxLayout(self.definition_tab)
|
||||
self.definition_layout.setContentsMargins(4, 4, 4, 4)
|
||||
definition.layouts(parent_tab=self.definition_tab)
|
||||
|
||||
# 添加标签页到主标签控件
|
||||
self.main_tab.addTab(self.geometry_tab, "几何模型")
|
||||
self.main_tab.addTab(self.rigging_tab, "绑定系统")
|
||||
self.main_tab.addTab(self.behaviour_tab, "行为系统")
|
||||
self.main_tab.addTab(self.definition_tab, "定义系统")
|
||||
|
||||
# 将组件添加到滚动区域内容布局
|
||||
self.scroll_content_layout.addWidget(self.toolbar_frame)
|
||||
self.scroll_content_layout.addWidget(self.main_tab)
|
||||
|
||||
# 设置滚动区域的内容控件
|
||||
self.scroll_area.setWidget(self.scroll_content)
|
||||
|
||||
# 将滚动区域和状态栏添加到主布局
|
||||
self.main_layout.addWidget(self.scroll_area)
|
||||
self.main_layout.addWidget(self.status_bar)
|
||||
|
||||
# 加载样式表
|
||||
|
||||
def load_stylesheet(self):
|
||||
"""加载样式表"""
|
||||
if os.path.exists(STYLE_FILE):
|
||||
try:
|
||||
with open(STYLE_FILE, "r", encoding="utf-8") as f:
|
||||
with open(STYLE_FILE, 'r', encoding='utf-8') as f:
|
||||
style = f.read()
|
||||
self.setStyleSheet(style)
|
||||
except UnicodeDecodeError:
|
||||
# 尝试使用系统默认编码
|
||||
encoding = get_system_encoding()
|
||||
try:
|
||||
with open(STYLE_FILE, "r", encoding=encoding) as f:
|
||||
style = f.read()
|
||||
self.setStyleSheet(style)
|
||||
except Exception as e:
|
||||
print(f"警告: 无法加载样式表文件: {e}")
|
||||
print(f"样式表已加载: {STYLE_FILE}")
|
||||
except Exception as e:
|
||||
print(f"加载样式表失败: {e}")
|
||||
else:
|
||||
print(f"警告: 样式表文件不存在: {STYLE_FILE}")
|
||||
|
||||
def create_connections(self):
|
||||
# 连接各模块的信号和槽
|
||||
toolbar.connections()
|
||||
geometry.connections()
|
||||
rigging.connections()
|
||||
behaviour.connections()
|
||||
definition.connections()
|
||||
print(f"样式表文件不存在: {STYLE_FILE}")
|
||||
|
||||
#========================================= WIDGET =======================================
|
||||
def create_widgets(self):
|
||||
"""创建UI控件"""
|
||||
# 主标签页控件
|
||||
self.main_tab_widget = QtWidgets.QTabWidget()
|
||||
self.main_tab_widget.setObjectName("mainTabWidget")
|
||||
|
||||
# 创建各个标签页
|
||||
self.toolbar_tab = QtWidgets.QWidget()
|
||||
self.definition_tab = QtWidgets.QWidget()
|
||||
self.geometry_tab = QtWidgets.QWidget()
|
||||
self.rigging_tab = QtWidgets.QWidget()
|
||||
self.behaviour_tab = QtWidgets.QWidget()
|
||||
|
||||
# 设置标签页名称
|
||||
self.main_tab_widget.addTab(self.toolbar_tab, LANG.get("toolbar", "工具栏"))
|
||||
self.main_tab_widget.addTab(self.definition_tab, LANG.get("definition", "定义"))
|
||||
self.main_tab_widget.addTab(self.geometry_tab, LANG.get("geometry", "几何体"))
|
||||
self.main_tab_widget.addTab(self.rigging_tab, LANG.get("rigging", "绑定"))
|
||||
self.main_tab_widget.addTab(self.behaviour_tab, LANG.get("behaviour", "行为"))
|
||||
|
||||
#========================================= LAYOUT =======================================
|
||||
def create_layouts(self):
|
||||
"""创建布局"""
|
||||
# 主布局
|
||||
main_layout = QtWidgets.QVBoxLayout(self)
|
||||
main_layout.setContentsMargins(5, 5, 5, 5)
|
||||
main_layout.setSpacing(5)
|
||||
main_layout.addWidget(self.main_tab_widget)
|
||||
|
||||
# 设置各标签页的布局
|
||||
toolbar_layout = QtWidgets.QVBoxLayout(self.toolbar_tab)
|
||||
definition_layout = QtWidgets.QVBoxLayout(self.definition_tab)
|
||||
geometry_layout = QtWidgets.QVBoxLayout(self.geometry_tab)
|
||||
rigging_layout = QtWidgets.QVBoxLayout(self.rigging_tab)
|
||||
behaviour_layout = QtWidgets.QVBoxLayout(self.behaviour_tab)
|
||||
|
||||
# 将各UI模块添加到对应的标签页布局中
|
||||
# 工具栏UI
|
||||
if hasattr(self.toolbar_ui, 'main_widget'):
|
||||
toolbar_layout.addWidget(self.toolbar_ui.main_widget)
|
||||
|
||||
# 定义UI
|
||||
if hasattr(self.definition_ui, 'main_widget'):
|
||||
definition_layout.addWidget(self.definition_ui.main_widget)
|
||||
|
||||
# 几何体UI
|
||||
if hasattr(self.geometry_ui, 'main_widget'):
|
||||
geometry_layout.addWidget(self.geometry_ui.main_widget)
|
||||
|
||||
# 绑定UI
|
||||
if hasattr(self.rigging_ui, 'main_widget'):
|
||||
rigging_layout.addWidget(self.rigging_ui.main_widget)
|
||||
|
||||
# 行为UI
|
||||
if hasattr(self.behaviour_ui, 'main_widget'):
|
||||
behaviour_layout.addWidget(self.behaviour_ui.main_widget)
|
||||
|
||||
#======================================= CONNECTION =====================================
|
||||
def create_connections(self):
|
||||
"""连接信号和槽"""
|
||||
# 标签页切换信号
|
||||
self.main_tab.currentChanged.connect(self.on_tab_changed)
|
||||
self.main_tab_widget.currentChanged.connect(self.tab_changed)
|
||||
|
||||
def on_tab_changed(self, index):
|
||||
tab_name = self.main_tab.tabText(index)
|
||||
self.status_bar.showMessage(f"当前模块: {tab_name}")
|
||||
print(f"切换到模块: {tab_name}")
|
||||
def tab_changed(self, index):
|
||||
"""标签页切换事件处理"""
|
||||
tab_name = self.main_tab_widget.tabText(index)
|
||||
print(f"切换到标签页: {tab_name}")
|
||||
|
||||
# 调整分割器宽度
|
||||
self.reset_splitters()
|
||||
|
||||
def reset_splitters(self):
|
||||
"""重置所有分割器的宽度,确保左右栏宽度均等"""
|
||||
# 延迟执行,确保UI完全加载
|
||||
QtCore.QTimer.singleShot(50, self._do_reset_splitters)
|
||||
QtCore.QTimer.singleShot(200, self._do_reset_splitters)
|
||||
|
||||
def _do_reset_splitters(self):
|
||||
"""实际执行分割器宽度重置的函数"""
|
||||
current_tab = self.main_tab_widget.currentWidget()
|
||||
if not current_tab:
|
||||
return
|
||||
|
||||
# 查找当前标签页中的所有水平分割器
|
||||
splitters = current_tab.findChildren(QtWidgets.QSplitter)
|
||||
for splitter in splitters:
|
||||
if splitter.orientation() == QtCore.Qt.Horizontal:
|
||||
# 获取分割器宽度
|
||||
width = splitter.width()
|
||||
# 计算每个部分应该的宽度
|
||||
count = splitter.count()
|
||||
if count > 0:
|
||||
part_width = width // count
|
||||
sizes = [part_width] * count
|
||||
# 设置分割器各部分的宽度
|
||||
splitter.setSizes(sizes)
|
||||
# 为每个子项设置相同的伸缩因子
|
||||
for i in range(count):
|
||||
splitter.setStretchFactor(i, 1)
|
||||
|
||||
def main():
|
||||
"""
|
||||
Main function to initialize and show the Plugin UI
|
||||
"""
|
||||
"""主函数,创建并显示主窗口"""
|
||||
try:
|
||||
# Initialize UI modules with placeholder functions
|
||||
# Each module only contains UI framework without actual functionality
|
||||
toolbar.toolbar_temp_function()
|
||||
geometry.geometry_temp_function()
|
||||
rigging.rigging_temp_function()
|
||||
behaviour.behaviour_temp_function()
|
||||
definition.definition_temp_function()
|
||||
# 如果已存在窗口,则关闭
|
||||
for widget in QtWidgets.QApplication.allWidgets():
|
||||
if widget.objectName() == f"{TOOL_NAME}MainWindow" and isinstance(widget, QtWidgets.QWidget):
|
||||
widget.close()
|
||||
widget.deleteLater()
|
||||
|
||||
# Create and show main window
|
||||
global tool_window
|
||||
tool_window = MainWindow()
|
||||
tool_window.dock_to_maya()
|
||||
|
||||
print(f"{TOOL_NAME} plugin initialized successfully!")
|
||||
return tool_window
|
||||
# 创建新窗口
|
||||
window = MainWindow()
|
||||
window.show()
|
||||
return window
|
||||
except Exception as e:
|
||||
error_msg = f"Error initializing {TOOL_NAME} plugin: {str(e)}"
|
||||
print(error_msg)
|
||||
traceback.print_exc()
|
||||
cmds.warning(error_msg)
|
||||
error_msg = traceback.format_exc()
|
||||
print(f"启动失败: {e}\n{error_msg}")
|
||||
return None
|
||||
|
||||
|
||||
# Auto-run when imported
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
@@ -1,43 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
MetaHuman DNA工具包
|
||||
|
||||
这个包包含了用于处理MetaHuman DNA文件的工具和实用程序。
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
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
|
||||
DEFAULT_ICON = os.path.join(ICONS_PATH, "commandButton.png").replace("\\", "/")
|
||||
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
|
||||
|
||||
|
||||
# 确保项目路径在sys.path中
|
||||
if TOOL_PATH not in sys.path:
|
||||
sys.path.insert(0, TOOL_PATH)
|
||||
|
||||
# 确保scripts路径在sys.path中
|
||||
if SCRIPTS_PATH not in sys.path:
|
||||
sys.path.insert(0, SCRIPTS_PATH)
|
||||
from . import *
|
@@ -4,6 +4,7 @@
|
||||
"""
|
||||
Behaviour UI Module for Plugin
|
||||
行为系统UI模块 - 负责显示角色行为编辑界面和基础操作
|
||||
|
||||
基本功能:
|
||||
- Blendshape自动加载,刷新,筛选
|
||||
- 次级Blendshape自动加载,刷新,筛选
|
||||
@@ -11,530 +12,249 @@ Behaviour UI Module for Plugin
|
||||
- Blendshape范围编辑
|
||||
- Blendshape镜像
|
||||
- Blendshape查找翻转目标
|
||||
- Blendshape重建
|
||||
- 表情控制器还原默认表情
|
||||
- 查找选择表情
|
||||
- 控制面板查找
|
||||
- 选择关联关节
|
||||
- 写入当前表情
|
||||
- 写入镜像表情
|
||||
"""
|
||||
|
||||
#===================================== IMPORT MODULES =====================================
|
||||
#========================================= 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
|
||||
|
||||
#===================================== IMPORT FUNCTIONS ===================================
|
||||
from scripts.utils import utils_behaviour as utils_behaviour
|
||||
from scripts.ui import ui_utils
|
||||
from scripts.utils import utils_behaviour
|
||||
#========================================== 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
|
||||
|
||||
#========================================== WIDGETS ==========================================
|
||||
# 全局变量存储UI控件
|
||||
blendshape_tree = None
|
||||
sub_blendshape_tree = None
|
||||
blendshape_slider = None
|
||||
blendshape_preview = None
|
||||
search_input = None
|
||||
weight_value = None
|
||||
right_slider = None
|
||||
right_value = None
|
||||
restore_button = None
|
||||
combo_select_button = None
|
||||
single_target_button = None
|
||||
combo_target_button = None
|
||||
batch_target_button = None
|
||||
add_target_button = None
|
||||
remove_target_button = None
|
||||
mirror_target_button = None
|
||||
flip_target_button = None
|
||||
plus_button = None
|
||||
all_button = None
|
||||
number_buttons_layout = None
|
||||
|
||||
# 全局布局变量
|
||||
search_layout = None
|
||||
left_bottom_buttons = None
|
||||
left_slider_layout = None
|
||||
left_bottom_layout = None
|
||||
right_slider_layout = None
|
||||
right_buttons_row1 = None
|
||||
right_buttons_row2 = None
|
||||
right_buttons_row3 = None
|
||||
tab_buttons = None
|
||||
bottom_slider_layout = None
|
||||
bottom_slider = None
|
||||
bottom_value = None
|
||||
bottom_buttons_row1 = None
|
||||
bottom_buttons_row2 = None
|
||||
|
||||
behaviour_buttons = {}
|
||||
|
||||
def set_button_icon(button, icon_name):
|
||||
class BehaviourUI(ui_utils.BaseUI):
|
||||
"""
|
||||
设置按钮图标,使用Maya默认图标
|
||||
|
||||
Args:
|
||||
button: 要设置图标的按钮
|
||||
icon_name: 图标文件名
|
||||
行为系统UI类 - 负责显示角色行为编辑界面和基础操作
|
||||
继承自BaseUI类,实现行为系统相关的UI功能
|
||||
"""
|
||||
# 使用Maya内置图标
|
||||
from maya import cmds
|
||||
|
||||
# 设置按钮图标使用Maya的图标
|
||||
button.setIcon(QtGui.QIcon(":/{}".format(icon_name)))
|
||||
button.setIconSize(QtCore.QSize(24, 24)) # 图标尺寸
|
||||
print(f"成功设置按钮图标: {icon_name}")
|
||||
|
||||
# 注意:如果图标加载失败,我们会看到一个空图标,但不会引起错误
|
||||
#========================================== INIT ========================================
|
||||
def __init__(self):
|
||||
"""
|
||||
初始化行为系统UI
|
||||
创建主控件和布局,并连接信号和槽
|
||||
"""
|
||||
super(BehaviourUI, self).__init__()
|
||||
|
||||
# 创建主控件
|
||||
self.main_widget = QtWidgets.QWidget()
|
||||
self.main_widget.setObjectName("behaviourMainWidget")
|
||||
|
||||
# 初始化UI
|
||||
self.create_widgets()
|
||||
self.create_layouts()
|
||||
self.create_connections()
|
||||
|
||||
def widgets():
|
||||
"""
|
||||
创建行为系统UI控件
|
||||
"""
|
||||
global blendshape_tree, sub_blendshape_tree, blendshape_slider, blendshape_preview, behaviour_buttons
|
||||
global search_input, weight_value, right_slider, right_value, restore_button, combo_select_button
|
||||
global single_target_button, combo_target_button, batch_target_button, add_target_button
|
||||
global remove_target_button, mirror_target_button, flip_target_button, plus_button, all_button
|
||||
global number_buttons_layout
|
||||
|
||||
# 全局布局变量
|
||||
global search_layout, left_bottom_buttons, left_slider_layout, left_bottom_layout
|
||||
global right_slider_layout, right_buttons_row1, right_buttons_row2, right_buttons_row3
|
||||
global tab_buttons, bottom_slider_layout, bottom_slider, bottom_value
|
||||
global bottom_buttons_row1, bottom_buttons_row2
|
||||
|
||||
# 创建搜索框
|
||||
search_layout = QtWidgets.QHBoxLayout()
|
||||
search_icon = QtWidgets.QLabel()
|
||||
search_icon.setPixmap(QtGui.QIcon(":/magnifyGlass.png").pixmap(16, 16))
|
||||
search_input = QtWidgets.QLineEdit()
|
||||
search_input.setPlaceholderText("搜索...")
|
||||
search_input.setObjectName("SearchInput")
|
||||
|
||||
# 主表情控制列表
|
||||
blendshape_tree = QtWidgets.QListWidget()
|
||||
blendshape_tree.setObjectName("RawControlList")
|
||||
blendshape_tree.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
|
||||
|
||||
# 相关混合变形列表
|
||||
sub_blendshape_tree = QtWidgets.QListWidget()
|
||||
sub_blendshape_tree.setObjectName("RelatedBlendShapesList")
|
||||
sub_blendshape_tree.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
|
||||
|
||||
# 创建权重滑块和数值显示
|
||||
blendshape_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal)
|
||||
blendshape_slider.setMinimum(0)
|
||||
blendshape_slider.setMaximum(1000) # 使用更精细的值,对应到0-1.0
|
||||
blendshape_slider.setValue(0)
|
||||
blendshape_slider.setObjectName("WeightSlider")
|
||||
|
||||
# 权重数值显示
|
||||
weight_value = QtWidgets.QLineEdit("0.000")
|
||||
weight_value.setFixedWidth(50)
|
||||
weight_value.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||
weight_value.setObjectName("WeightValue")
|
||||
|
||||
# 全部按钮
|
||||
all_button = QtWidgets.QPushButton("全部")
|
||||
all_button.setFixedWidth(60)
|
||||
all_button.setObjectName("AllButton")
|
||||
|
||||
# 数字按钮组
|
||||
number_buttons_layout = QtWidgets.QHBoxLayout()
|
||||
for i in range(1, 7): # 1-6的数字按钮
|
||||
num_button = QtWidgets.QPushButton(str(i))
|
||||
num_button.setFixedWidth(30)
|
||||
num_button.setObjectName(f"NumButton{i}")
|
||||
number_buttons_layout.addWidget(num_button)
|
||||
|
||||
# 创建左侧底部按钮
|
||||
restore_button = QtWidgets.QPushButton("恢复表情")
|
||||
set_button_icon(restore_button, "undo.png")
|
||||
restore_button.setObjectName("RestoreButton")
|
||||
|
||||
combo_select_button = QtWidgets.QPushButton("组合选择")
|
||||
set_button_icon(combo_select_button, "selectByHull.png")
|
||||
combo_select_button.setObjectName("ComboSelectButton")
|
||||
|
||||
# 创建右侧按钮
|
||||
# 第一行按钮
|
||||
single_target_button = QtWidgets.QPushButton("单个目标表情")
|
||||
set_button_icon(single_target_button, "blendShape.png")
|
||||
single_target_button.setObjectName("SingleTargetButton")
|
||||
|
||||
combo_target_button = QtWidgets.QPushButton("复合目标表情")
|
||||
set_button_icon(combo_target_button, "blendShapeEditor.png")
|
||||
combo_target_button.setObjectName("ComboTargetButton")
|
||||
|
||||
batch_target_button = QtWidgets.QPushButton("批量目标表情")
|
||||
set_button_icon(batch_target_button, "blendShapePanel.png")
|
||||
batch_target_button.setObjectName("BatchTargetButton")
|
||||
|
||||
# 第二行按钮
|
||||
add_target_button = QtWidgets.QPushButton("添加目标表情")
|
||||
set_button_icon(add_target_button, "addClip.png")
|
||||
add_target_button.setObjectName("AddTargetButton")
|
||||
|
||||
remove_target_button = QtWidgets.QPushButton("移除目标表情")
|
||||
set_button_icon(remove_target_button, "removeClip.png")
|
||||
remove_target_button.setObjectName("RemoveTargetButton")
|
||||
|
||||
# 第三行按钮
|
||||
mirror_target_button = QtWidgets.QPushButton("镜像目标表情")
|
||||
set_button_icon(mirror_target_button, "mirrorJoint.png")
|
||||
mirror_target_button.setObjectName("MirrorTargetButton")
|
||||
|
||||
flip_target_button = QtWidgets.QPushButton("翻转目标表情")
|
||||
set_button_icon(flip_target_button, "flipTriangle.png")
|
||||
flip_target_button.setObjectName("FlipTargetButton")
|
||||
|
||||
# 右侧滑块和数值显示
|
||||
right_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal)
|
||||
right_slider.setMinimum(0)
|
||||
right_slider.setMaximum(1000) # 使用更精细的值,对应到0-1.0
|
||||
right_slider.setValue(0)
|
||||
right_slider.setObjectName("RightSlider")
|
||||
|
||||
right_value = QtWidgets.QLineEdit("0.000")
|
||||
right_value.setFixedWidth(50)
|
||||
right_value.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||
right_value.setObjectName("RightValue")
|
||||
|
||||
# 添加加号按钮
|
||||
plus_button = QtWidgets.QPushButton("+")
|
||||
plus_button.setFixedSize(30, 30)
|
||||
plus_button.setObjectName("PlusButton")
|
||||
|
||||
# 底部按钮
|
||||
# 第一行按钮
|
||||
behaviour_buttons["reset_controller"] = QtWidgets.QPushButton("还原默认表情")
|
||||
set_button_icon(behaviour_buttons["reset_controller"], "undo.png")
|
||||
|
||||
behaviour_buttons["find_expression"] = QtWidgets.QPushButton("查找选择表情")
|
||||
set_button_icon(behaviour_buttons["find_expression"], "find.png")
|
||||
|
||||
behaviour_buttons["find_control_panel"] = QtWidgets.QPushButton("控制面板查找")
|
||||
set_button_icon(behaviour_buttons["find_control_panel"], "menuIconWindow.png")
|
||||
|
||||
# 第二行按钮
|
||||
behaviour_buttons["select_related_joints"] = QtWidgets.QPushButton("选择关联关节")
|
||||
set_button_icon(behaviour_buttons["select_related_joints"], "kinJoint.png")
|
||||
|
||||
behaviour_buttons["write_current_expression"] = QtWidgets.QPushButton("写入当前表情")
|
||||
set_button_icon(behaviour_buttons["write_current_expression"], "positionConstraint.png")
|
||||
|
||||
behaviour_buttons["write_mirror_expression"] = QtWidgets.QPushButton("写入镜像表情")
|
||||
set_button_icon(behaviour_buttons["write_mirror_expression"], "mirrorJoint.png")
|
||||
|
||||
# 设置所有按钮的样式
|
||||
for key, button in behaviour_buttons.items():
|
||||
button.setMinimumHeight(28)
|
||||
button.setStyleSheet("text-align: left; padding-left: 30px;")
|
||||
button.setToolTip(button.text())
|
||||
#========================================= WIDGET =======================================
|
||||
def create_widgets(self):
|
||||
"""
|
||||
创建行为系统UI控件
|
||||
包括按钮、标签、列表等
|
||||
"""
|
||||
# 标题标签
|
||||
self.controls["title_label"] = QtWidgets.QLabel(LANG.get("behaviour_title", "角色行为"))
|
||||
self.controls["title_label"].setObjectName("behaviourTitleLabel")
|
||||
self.controls["title_label"].setAlignment(QtCore.Qt.AlignCenter)
|
||||
|
||||
# 创建主分割器
|
||||
self.splitters["main_splitter"] = QtWidgets.QSplitter(QtCore.Qt.Horizontal)
|
||||
self.splitters["main_splitter"].setObjectName("behaviourMainSplitter")
|
||||
|
||||
# 左侧面板
|
||||
self.controls["left_panel"] = QtWidgets.QWidget()
|
||||
self.controls["left_panel"].setObjectName("behaviourLeftPanel")
|
||||
|
||||
# 右侧面板
|
||||
self.controls["right_panel"] = QtWidgets.QWidget()
|
||||
self.controls["right_panel"].setObjectName("behaviourRightPanel")
|
||||
|
||||
# 左侧面板控件
|
||||
# Blendshape列表组
|
||||
self.controls["blendshape_group"] = QtWidgets.QGroupBox(LANG.get("blendshape_group", "Blendshape列表"))
|
||||
self.controls["blendshape_group"].setObjectName("blendshapeGroup")
|
||||
|
||||
# Blendshape列表
|
||||
self.controls["blendshape_list"] = QtWidgets.QListWidget()
|
||||
self.controls["blendshape_list"].setObjectName("blendshapeList")
|
||||
|
||||
# Blendshape刷新按钮
|
||||
self.buttons["refresh_blendshape"] = QtWidgets.QPushButton(LANG.get("refresh", "刷新"))
|
||||
self.buttons["refresh_blendshape"].setObjectName("refreshBlendshapeButton")
|
||||
|
||||
# Blendshape过滤组
|
||||
self.controls["blendshape_filter_group"] = QtWidgets.QGroupBox(LANG.get("blendshape_filter", "Blendshape过滤"))
|
||||
self.controls["blendshape_filter_group"].setObjectName("blendshapeFilterGroup")
|
||||
|
||||
# Blendshape过滤输入框
|
||||
self.controls["blendshape_filter_input"] = QtWidgets.QLineEdit()
|
||||
self.controls["blendshape_filter_input"].setObjectName("blendshapeFilterInput")
|
||||
self.controls["blendshape_filter_input"].setPlaceholderText(LANG.get("filter_placeholder", "输入过滤条件"))
|
||||
|
||||
# 次级Blendshape列表组
|
||||
self.controls["secondary_blendshape_group"] = QtWidgets.QGroupBox(LANG.get("secondary_blendshape_group", "次级Blendshape"))
|
||||
self.controls["secondary_blendshape_group"].setObjectName("secondaryBlendshapeGroup")
|
||||
|
||||
# 次级Blendshape列表
|
||||
self.controls["secondary_blendshape_list"] = QtWidgets.QListWidget()
|
||||
self.controls["secondary_blendshape_list"].setObjectName("secondaryBlendshapeList")
|
||||
|
||||
# 次级Blendshape刷新按钮
|
||||
self.buttons["refresh_secondary_blendshape"] = QtWidgets.QPushButton(LANG.get("refresh", "刷新"))
|
||||
self.buttons["refresh_secondary_blendshape"].setObjectName("refreshSecondaryBlendshapeButton")
|
||||
|
||||
# 右侧面板控件
|
||||
# Blendshape操作组
|
||||
self.controls["blendshape_ops_group"] = QtWidgets.QGroupBox(LANG.get("blendshape_operations", "Blendshape操作"))
|
||||
self.controls["blendshape_ops_group"].setObjectName("blendshapeOpsGroup")
|
||||
|
||||
# Blendshape操作按钮
|
||||
self.buttons["export_blendshape"] = QtWidgets.QPushButton(LANG.get("export_blendshape", "导出Blendshape"))
|
||||
self.buttons["import_blendshape"] = QtWidgets.QPushButton(LANG.get("import_blendshape", "导入Blendshape"))
|
||||
self.buttons["edit_range"] = QtWidgets.QPushButton(LANG.get("edit_range", "编辑范围"))
|
||||
self.buttons["mirror_blendshape"] = QtWidgets.QPushButton(LANG.get("mirror_blendshape", "镜像Blendshape"))
|
||||
self.buttons["find_flip_target"] = QtWidgets.QPushButton(LANG.get("find_flip_target", "查找翻转目标"))
|
||||
|
||||
# 表情控制组
|
||||
self.controls["expression_control_group"] = QtWidgets.QGroupBox(LANG.get("expression_control", "表情控制"))
|
||||
self.controls["expression_control_group"].setObjectName("expressionControlGroup")
|
||||
|
||||
# 表情控制按钮
|
||||
self.buttons["reset_expression"] = QtWidgets.QPushButton(LANG.get("reset_expression", "还原默认表情"))
|
||||
self.buttons["find_expression"] = QtWidgets.QPushButton(LANG.get("find_expression", "查找选择表情"))
|
||||
self.buttons["find_control_panel"] = QtWidgets.QPushButton(LANG.get("find_control_panel", "控制面板查找"))
|
||||
|
||||
#========================================== LAYOUTS ==========================================
|
||||
def layouts(parent_tab=None):
|
||||
"""
|
||||
创建行为系统UI布局
|
||||
|
||||
Args:
|
||||
parent_tab: 父容器控件,由Main.py传入
|
||||
"""
|
||||
# 获取父容器(在Main.py中创建的behaviour_tab)
|
||||
if not parent_tab:
|
||||
parent_tab = ui_utils.get_parent_widget("behaviour_tab")
|
||||
if not parent_tab:
|
||||
print("无法获取父容器,布局创建失败")
|
||||
return
|
||||
|
||||
# 创建主布局
|
||||
main_layout = parent_tab.layout()
|
||||
if not main_layout:
|
||||
main_layout = QtWidgets.QVBoxLayout(parent_tab)
|
||||
main_layout.setContentsMargins(4, 4, 4, 4)
|
||||
main_layout.setSpacing(4)
|
||||
main_layout.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint) # 设置布局约束为默认,允许自适应
|
||||
|
||||
# 创建主分割控件
|
||||
main_splitter = QtWidgets.QSplitter(QtCore.Qt.Horizontal)
|
||||
|
||||
# 左侧区域 - Raw Control
|
||||
left_widget = QtWidgets.QWidget()
|
||||
left_layout = QtWidgets.QVBoxLayout(left_widget)
|
||||
left_layout.setContentsMargins(2, 2, 2, 2)
|
||||
left_layout.setSpacing(2)
|
||||
|
||||
# 标题和搜索区域
|
||||
left_header = QtWidgets.QHBoxLayout()
|
||||
left_title = QtWidgets.QLabel("Raw Control [000]")
|
||||
left_title.setStyleSheet("font-weight: bold;")
|
||||
left_header.addWidget(left_title)
|
||||
left_layout.addLayout(left_header)
|
||||
|
||||
# 搜索框
|
||||
search_layout = QtWidgets.QHBoxLayout()
|
||||
search_icon = QtWidgets.QLabel()
|
||||
search_icon.setPixmap(QtGui.QIcon(":/magnifyGlass.png").pixmap(16, 16))
|
||||
search_layout.addWidget(search_icon)
|
||||
search_layout.addWidget(search_input)
|
||||
left_layout.addLayout(search_layout)
|
||||
|
||||
# 主列表
|
||||
left_layout.addWidget(blendshape_tree)
|
||||
|
||||
# 底部按钮组
|
||||
left_bottom_buttons = QtWidgets.QHBoxLayout()
|
||||
left_bottom_buttons.addWidget(restore_button)
|
||||
left_bottom_buttons.addWidget(combo_select_button)
|
||||
left_layout.addLayout(left_bottom_buttons)
|
||||
|
||||
# 数字按钮组
|
||||
left_layout.addWidget(all_button)
|
||||
left_layout.addLayout(number_buttons_layout)
|
||||
|
||||
# 底部滑块和数值
|
||||
left_slider_layout = QtWidgets.QHBoxLayout()
|
||||
left_slider_layout.addWidget(weight_value)
|
||||
left_slider_layout.addWidget(blendshape_slider)
|
||||
left_slider_layout.addWidget(QtWidgets.QPushButton("全部"))
|
||||
left_layout.addLayout(left_slider_layout)
|
||||
|
||||
# 左侧底部按钮组
|
||||
left_bottom_layout = QtWidgets.QHBoxLayout()
|
||||
left_bottom_layout.addWidget(QtWidgets.QPushButton("定义"))
|
||||
left_bottom_layout.addWidget(QtWidgets.QPushButton("范围 -"))
|
||||
left_layout.addLayout(left_bottom_layout)
|
||||
|
||||
# 右侧区域 - Related BlendShapes
|
||||
right_widget = QtWidgets.QWidget()
|
||||
right_layout = QtWidgets.QVBoxLayout(right_widget)
|
||||
right_layout.setContentsMargins(2, 2, 2, 2)
|
||||
right_layout.setSpacing(2)
|
||||
|
||||
# 标题
|
||||
right_header = QtWidgets.QHBoxLayout()
|
||||
right_title = QtWidgets.QLabel("Related BlendShapes [000]")
|
||||
right_title.setStyleSheet("font-weight: bold;")
|
||||
right_header.addWidget(right_title)
|
||||
right_layout.addLayout(right_header)
|
||||
|
||||
# 相关混合变形列表
|
||||
right_layout.addWidget(sub_blendshape_tree)
|
||||
|
||||
# 右侧滑块和数值
|
||||
right_slider_layout = QtWidgets.QHBoxLayout()
|
||||
right_slider_layout.addWidget(right_value)
|
||||
right_slider_layout.addWidget(right_slider)
|
||||
right_slider_layout.addWidget(QtWidgets.QPushButton("全部"))
|
||||
right_layout.addLayout(right_slider_layout)
|
||||
|
||||
# 右侧按钮组 - 第一行
|
||||
right_buttons_row1 = QtWidgets.QHBoxLayout()
|
||||
right_buttons_row1.addWidget(single_target_button)
|
||||
right_buttons_row1.addWidget(combo_target_button)
|
||||
right_buttons_row1.addWidget(batch_target_button)
|
||||
right_layout.addLayout(right_buttons_row1)
|
||||
|
||||
# 右侧按钮组 - 第二行
|
||||
right_buttons_row2 = QtWidgets.QHBoxLayout()
|
||||
right_buttons_row2.addWidget(add_target_button)
|
||||
right_buttons_row2.addWidget(remove_target_button)
|
||||
right_layout.addLayout(right_buttons_row2)
|
||||
|
||||
# 右侧按钮组 - 第三行
|
||||
right_buttons_row3 = QtWidgets.QHBoxLayout()
|
||||
right_buttons_row3.addWidget(mirror_target_button)
|
||||
right_buttons_row3.addWidget(flip_target_button)
|
||||
right_layout.addLayout(right_buttons_row3)
|
||||
|
||||
# 添加到主分割控件
|
||||
main_splitter.addWidget(left_widget)
|
||||
main_splitter.addWidget(right_widget)
|
||||
|
||||
# 设置分割比例
|
||||
main_splitter.setSizes([int(parent_tab.width() * 0.5), int(parent_tab.width() * 0.5)])
|
||||
|
||||
# 底部按钮组
|
||||
bottom_widget = QtWidgets.QWidget()
|
||||
bottom_layout = QtWidgets.QVBoxLayout(bottom_widget)
|
||||
bottom_layout.setContentsMargins(4, 4, 4, 4)
|
||||
bottom_layout.setSpacing(4)
|
||||
|
||||
# 选项卡按钮组
|
||||
tab_buttons = QtWidgets.QHBoxLayout()
|
||||
tab_buttons.addWidget(QtWidgets.QPushButton("BS"))
|
||||
tab_buttons.addWidget(QtWidgets.QPushButton("PSD"))
|
||||
tab_buttons.addWidget(QtWidgets.QPushButton("KEY"))
|
||||
tab_buttons.addWidget(QtWidgets.QPushButton("JNT"))
|
||||
tab_buttons.addWidget(QtWidgets.QPushButton("ARK"))
|
||||
tab_buttons.addWidget(QtWidgets.QPushButton("CTR"))
|
||||
bottom_layout.addLayout(tab_buttons)
|
||||
|
||||
# 底部滑块
|
||||
bottom_slider_layout = QtWidgets.QHBoxLayout()
|
||||
bottom_slider = QtWidgets.QSlider(QtCore.Qt.Horizontal)
|
||||
bottom_slider.setMinimum(0)
|
||||
bottom_slider.setMaximum(1000)
|
||||
bottom_slider.setValue(0)
|
||||
bottom_value = QtWidgets.QLineEdit("0.000")
|
||||
bottom_value.setFixedWidth(50)
|
||||
bottom_value.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||
bottom_slider_layout.addWidget(bottom_value)
|
||||
bottom_slider_layout.addWidget(bottom_slider)
|
||||
bottom_slider_layout.addWidget(plus_button)
|
||||
bottom_slider_layout.addWidget(QtWidgets.QPushButton("全部"))
|
||||
bottom_layout.addLayout(bottom_slider_layout)
|
||||
|
||||
# 底部按钮组 - 第一行
|
||||
bottom_buttons_row1 = QtWidgets.QHBoxLayout()
|
||||
bottom_buttons_row1.addWidget(behaviour_buttons["reset_controller"])
|
||||
bottom_buttons_row1.addWidget(behaviour_buttons["find_expression"])
|
||||
bottom_buttons_row1.addWidget(behaviour_buttons["write_current_expression"])
|
||||
bottom_layout.addLayout(bottom_buttons_row1)
|
||||
|
||||
# 底部按钮组 - 第二行
|
||||
bottom_buttons_row2 = QtWidgets.QHBoxLayout()
|
||||
bottom_buttons_row2.addWidget(behaviour_buttons["find_control_panel"])
|
||||
bottom_buttons_row2.addWidget(behaviour_buttons["select_related_joints"])
|
||||
bottom_buttons_row2.addWidget(behaviour_buttons["write_mirror_expression"])
|
||||
bottom_layout.addLayout(bottom_buttons_row2)
|
||||
|
||||
# 添加到主布局
|
||||
main_layout.addWidget(main_splitter, 3) # 占据更多空间
|
||||
main_layout.addWidget(bottom_widget, 1) # 占据较少空间
|
||||
#========================================= LAYOUT =======================================
|
||||
def create_layouts(self):
|
||||
"""
|
||||
创建行为系统UI布局
|
||||
组织控件的排列和层次结构
|
||||
"""
|
||||
# 主布局
|
||||
self.layouts["main_layout"] = QtWidgets.QVBoxLayout(self.main_widget)
|
||||
self.layouts["main_layout"].setContentsMargins(5, 5, 5, 5)
|
||||
self.layouts["main_layout"].setSpacing(5)
|
||||
|
||||
# 添加标题标签
|
||||
self.layouts["main_layout"].addWidget(self.controls["title_label"])
|
||||
|
||||
# 添加主分割器
|
||||
self.layouts["main_layout"].addWidget(self.splitters["main_splitter"])
|
||||
|
||||
# 将左右面板添加到主分割器
|
||||
self.splitters["main_splitter"].addWidget(self.controls["left_panel"])
|
||||
self.splitters["main_splitter"].addWidget(self.controls["right_panel"])
|
||||
|
||||
# 左侧面板布局
|
||||
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)
|
||||
|
||||
# Blendshape列表组布局
|
||||
self.layouts["blendshape_layout"] = QtWidgets.QVBoxLayout(self.controls["blendshape_group"])
|
||||
self.layouts["blendshape_layout"].addWidget(self.controls["blendshape_list"])
|
||||
self.layouts["blendshape_layout"].addWidget(self.buttons["refresh_blendshape"])
|
||||
|
||||
# Blendshape过滤组布局
|
||||
self.layouts["blendshape_filter_layout"] = QtWidgets.QVBoxLayout(self.controls["blendshape_filter_group"])
|
||||
self.layouts["blendshape_filter_layout"].addWidget(self.controls["blendshape_filter_input"])
|
||||
|
||||
# 次级Blendshape列表组布局
|
||||
self.layouts["secondary_blendshape_layout"] = QtWidgets.QVBoxLayout(self.controls["secondary_blendshape_group"])
|
||||
self.layouts["secondary_blendshape_layout"].addWidget(self.controls["secondary_blendshape_list"])
|
||||
self.layouts["secondary_blendshape_layout"].addWidget(self.buttons["refresh_secondary_blendshape"])
|
||||
|
||||
# 添加组到左侧面板布局
|
||||
self.layouts["left_layout"].addWidget(self.controls["blendshape_group"])
|
||||
self.layouts["left_layout"].addWidget(self.controls["blendshape_filter_group"])
|
||||
self.layouts["left_layout"].addWidget(self.controls["secondary_blendshape_group"])
|
||||
self.layouts["left_layout"].addStretch()
|
||||
|
||||
# 右侧面板布局
|
||||
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)
|
||||
|
||||
# Blendshape操作组布局
|
||||
self.layouts["blendshape_ops_layout"] = QtWidgets.QVBoxLayout(self.controls["blendshape_ops_group"])
|
||||
self.layouts["blendshape_ops_layout"].addWidget(self.buttons["export_blendshape"])
|
||||
self.layouts["blendshape_ops_layout"].addWidget(self.buttons["import_blendshape"])
|
||||
self.layouts["blendshape_ops_layout"].addWidget(self.buttons["edit_range"])
|
||||
self.layouts["blendshape_ops_layout"].addWidget(self.buttons["mirror_blendshape"])
|
||||
self.layouts["blendshape_ops_layout"].addWidget(self.buttons["find_flip_target"])
|
||||
|
||||
# 表情控制组布局
|
||||
self.layouts["expression_control_layout"] = QtWidgets.QVBoxLayout(self.controls["expression_control_group"])
|
||||
self.layouts["expression_control_layout"].addWidget(self.buttons["reset_expression"])
|
||||
self.layouts["expression_control_layout"].addWidget(self.buttons["find_expression"])
|
||||
self.layouts["expression_control_layout"].addWidget(self.buttons["find_control_panel"])
|
||||
|
||||
# 添加组到右侧面板布局
|
||||
self.layouts["right_layout"].addWidget(self.controls["blendshape_ops_group"])
|
||||
self.layouts["right_layout"].addWidget(self.controls["expression_control_group"])
|
||||
self.layouts["right_layout"].addStretch()
|
||||
|
||||
# 创建分割器大小处理器
|
||||
self.resize_handlers["main_splitter"] = ui_utils.SplitterResizeHandler(
|
||||
self.main_widget, self.splitters["main_splitter"], is_horizontal=True
|
||||
)
|
||||
|
||||
#========================================== CONNECTIONS ==========================================
|
||||
def connections():
|
||||
"""
|
||||
连接行为系统UI信号和槽
|
||||
"""
|
||||
# 连接主表情控制列表选择事件
|
||||
blendshape_tree.itemSelectionChanged.connect(on_blendshape_selection_changed)
|
||||
sub_blendshape_tree.itemSelectionChanged.connect(on_sub_blendshape_selection_changed)
|
||||
|
||||
# 连接滑块值变化事件
|
||||
blendshape_slider.valueChanged.connect(on_blendshape_slider_changed)
|
||||
|
||||
# 连接底部按钮点击事件
|
||||
behaviour_buttons["reset_controller"].clicked.connect(on_reset_controller)
|
||||
behaviour_buttons["find_expression"].clicked.connect(on_find_expression)
|
||||
behaviour_buttons["find_control_panel"].clicked.connect(on_find_control_panel)
|
||||
behaviour_buttons["select_related_joints"].clicked.connect(on_select_related_joints)
|
||||
behaviour_buttons["write_current_expression"].clicked.connect(on_write_current_expression)
|
||||
behaviour_buttons["write_mirror_expression"].clicked.connect(on_write_mirror_expression)
|
||||
|
||||
# 连接其他按钮点击事件
|
||||
restore_button.clicked.connect(on_restore_expression)
|
||||
combo_select_button.clicked.connect(on_combo_select)
|
||||
|
||||
# 连接右侧按钮点击事件
|
||||
single_target_button.clicked.connect(on_single_target)
|
||||
combo_target_button.clicked.connect(on_combo_target)
|
||||
batch_target_button.clicked.connect(on_batch_target)
|
||||
add_target_button.clicked.connect(on_add_target)
|
||||
remove_target_button.clicked.connect(on_remove_target)
|
||||
mirror_target_button.clicked.connect(on_mirror_target)
|
||||
flip_target_button.clicked.connect(on_flip_target)
|
||||
|
||||
#===================================== CALLBACK FUNCTIONS ===================================
|
||||
def on_blendshape_selection_changed():
|
||||
"""当主表情控制列表选择变化时调用"""
|
||||
print("主表情控制选择已更改")
|
||||
# TODO: 实现选择变化后的逻辑
|
||||
|
||||
def on_sub_blendshape_selection_changed():
|
||||
"""当相关混合变形列表选择变化时调用"""
|
||||
print("相关混合变形选择已更改")
|
||||
# TODO: 实现选择变化后的逻辑
|
||||
|
||||
def on_blendshape_slider_changed(value):
|
||||
"""当混合变形滑块值变化时调用"""
|
||||
actual_value = value / 1000.0 # 转换为0-1范围
|
||||
print(f"混合变形权重已更改为: {actual_value:.3f}")
|
||||
# TODO: 实现权重变化后的逻辑
|
||||
|
||||
def on_reset_controller():
|
||||
"""还原默认表情"""
|
||||
print("还原默认表情功能待实现")
|
||||
# TODO: 实现还原默认表情功能
|
||||
|
||||
def on_find_expression():
|
||||
"""查找选择表情"""
|
||||
print("查找选择表情功能待实现")
|
||||
# TODO: 实现查找选择表情功能
|
||||
|
||||
def on_find_control_panel():
|
||||
"""控制面板查找"""
|
||||
print("控制面板查找功能待实现")
|
||||
# TODO: 实现控制面板查找功能
|
||||
|
||||
def on_select_related_joints():
|
||||
"""选择关联关节"""
|
||||
print("选择关联关节功能待实现")
|
||||
# TODO: 实现选择关联关节功能
|
||||
|
||||
def on_write_current_expression():
|
||||
"""写入当前表情"""
|
||||
print("写入当前表情功能待实现")
|
||||
# TODO: 实现写入当前表情功能
|
||||
|
||||
def on_write_mirror_expression():
|
||||
"""写入镜像表情"""
|
||||
print("写入镜像表情功能待实现")
|
||||
# TODO: 实现写入镜像表情功能
|
||||
|
||||
def on_restore_expression():
|
||||
"""恢复表情"""
|
||||
print("恢复表情功能待实现")
|
||||
# TODO: 实现恢复表情功能
|
||||
|
||||
def on_combo_select():
|
||||
"""组合选择"""
|
||||
print("组合选择功能待实现")
|
||||
# TODO: 实现组合选择功能
|
||||
|
||||
def on_single_target():
|
||||
"""单个目标表情"""
|
||||
print("单个目标表情功能待实现")
|
||||
# TODO: 实现单个目标表情功能
|
||||
|
||||
def on_combo_target():
|
||||
"""复合目标表情"""
|
||||
print("复合目标表情功能待实现")
|
||||
# TODO: 实现复合目标表情功能
|
||||
|
||||
def on_batch_target():
|
||||
"""批量目标表情"""
|
||||
print("批量目标表情功能待实现")
|
||||
# TODO: 实现批量目标表情功能
|
||||
|
||||
def on_add_target():
|
||||
"""添加目标表情"""
|
||||
print("添加目标表情功能待实现")
|
||||
# TODO: 实现添加目标表情功能
|
||||
|
||||
def on_remove_target():
|
||||
"""移除目标表情"""
|
||||
print("移除目标表情功能待实现")
|
||||
# TODO: 实现移除目标表情功能
|
||||
|
||||
def on_mirror_target():
|
||||
"""镜像目标表情"""
|
||||
print("镜像目标表情功能待实现")
|
||||
# TODO: 实现镜像目标表情功能
|
||||
|
||||
def on_flip_target():
|
||||
"""翻转目标表情"""
|
||||
print("翻转目标表情功能待实现")
|
||||
# TODO: 实现翻转目标表情功能
|
||||
|
||||
#===================================== PLACEHOLDER FUNCTION ===================================
|
||||
def behaviour_temp_function():
|
||||
return utils_behaviour.behaviour_temp_utils_function()
|
||||
#======================================= CONNECTION =====================================
|
||||
def create_connections(self):
|
||||
"""
|
||||
连接信号和槽
|
||||
设置UI控件的交互行为
|
||||
"""
|
||||
# Blendshape列表按钮连接
|
||||
self.buttons["refresh_blendshape"].clicked.connect(utils_behaviour.behaviour_temp_utils_function)
|
||||
|
||||
# Blendshape过滤连接
|
||||
self.controls["blendshape_filter_input"].textChanged.connect(utils_behaviour.behaviour_temp_utils_function)
|
||||
|
||||
# 次级Blendshape按钮连接
|
||||
self.buttons["refresh_secondary_blendshape"].clicked.connect(utils_behaviour.behaviour_temp_utils_function)
|
||||
|
||||
# Blendshape操作按钮连接
|
||||
self.buttons["export_blendshape"].clicked.connect(utils_behaviour.behaviour_temp_utils_function)
|
||||
self.buttons["import_blendshape"].clicked.connect(utils_behaviour.behaviour_temp_utils_function)
|
||||
self.buttons["edit_range"].clicked.connect(utils_behaviour.behaviour_temp_utils_function)
|
||||
self.buttons["mirror_blendshape"].clicked.connect(utils_behaviour.behaviour_temp_utils_function)
|
||||
self.buttons["find_flip_target"].clicked.connect(utils_behaviour.behaviour_temp_utils_function)
|
||||
|
||||
# 表情控制按钮连接
|
||||
self.buttons["reset_expression"].clicked.connect(utils_behaviour.behaviour_temp_utils_function)
|
||||
self.buttons["find_expression"].clicked.connect(utils_behaviour.behaviour_temp_utils_function)
|
||||
self.buttons["find_control_panel"].clicked.connect(utils_behaviour.behaviour_temp_utils_function)
|
@@ -10,459 +10,266 @@ Definition UI Module for Plugin
|
||||
- 创建:创建混合变形,绑定蒙皮,取消蒙皮
|
||||
- 工具:重新定位头部关节,重新定位身体关节,重新定位全身关节,快速创建预设
|
||||
"""
|
||||
|
||||
#===================================== IMPORT MODULES =====================================
|
||||
#========================================= 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
|
||||
|
||||
#===================================== IMPORT FUNCTIONS ===================================
|
||||
from scripts.utils import utils_definition as utils_definition
|
||||
from scripts.ui import ui_utils
|
||||
from scripts.utils import utils_definition
|
||||
#========================================== 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
|
||||
|
||||
#========================================== WIDGETS ==========================================
|
||||
# 全局变量存储UI控件
|
||||
definition_tabs = None
|
||||
dna_elements = {}
|
||||
definition_buttons = {}
|
||||
class DefinitionUI(ui_utils.BaseUI):
|
||||
"""
|
||||
定义系统UI类 - 负责显示DNA定义编辑界面和基础操作
|
||||
继承自BaseUI类,实现DNA定义相关的UI功能
|
||||
"""
|
||||
#========================================== INIT ========================================
|
||||
def __init__(self):
|
||||
"""
|
||||
初始化定义系统UI
|
||||
创建主控件和布局,并连接信号和槽
|
||||
"""
|
||||
super(DefinitionUI, self).__init__()
|
||||
|
||||
# 创建主控件
|
||||
self.main_widget = QtWidgets.QWidget()
|
||||
self.main_widget.setObjectName("definitionMainWidget")
|
||||
|
||||
# 初始化UI
|
||||
self.create_widgets()
|
||||
self.create_layouts()
|
||||
self.create_connections()
|
||||
|
||||
def set_button_icon(button, icon_name):
|
||||
"""
|
||||
设置按钮图标,使用Maya默认图标
|
||||
|
||||
Args:
|
||||
button: 要设置图标的按钮
|
||||
icon_name: 图标文件名
|
||||
"""
|
||||
# 使用Maya内置图标
|
||||
from maya import cmds
|
||||
|
||||
# 设置按钮图标使用Maya的图标
|
||||
button.setIcon(QtGui.QIcon(":/{}".format(icon_name)))
|
||||
button.setIconSize(QtCore.QSize(24, 24)) # 图标尺寸
|
||||
print(f"成功设置按钮图标: {icon_name}")
|
||||
|
||||
# 注意:如果图标加载失败,我们会看到一个空图标,但不会引起错误
|
||||
#========================================= WIDGET =======================================
|
||||
def create_widgets(self):
|
||||
"""
|
||||
创建定义系统UI控件
|
||||
包括按钮、标签、列表等
|
||||
"""
|
||||
# 标题标签
|
||||
self.controls["title_label"] = QtWidgets.QLabel(LANG.get("definition_title", "DNA定义"))
|
||||
self.controls["title_label"].setObjectName("definitionTitleLabel")
|
||||
self.controls["title_label"].setAlignment(QtCore.Qt.AlignCenter)
|
||||
|
||||
# 创建主分割器
|
||||
self.splitters["main_splitter"] = QtWidgets.QSplitter(QtCore.Qt.Horizontal)
|
||||
self.splitters["main_splitter"].setObjectName("definitionMainSplitter")
|
||||
|
||||
# 左侧面板
|
||||
self.controls["left_panel"] = QtWidgets.QWidget()
|
||||
self.controls["left_panel"].setObjectName("definitionLeftPanel")
|
||||
|
||||
# 右侧面板
|
||||
self.controls["right_panel"] = QtWidgets.QWidget()
|
||||
self.controls["right_panel"].setObjectName("definitionRightPanel")
|
||||
|
||||
# 左侧面板控件
|
||||
# LOD组
|
||||
self.controls["lod_group"] = QtWidgets.QGroupBox(LANG.get("lod_group", "LOD"))
|
||||
self.controls["lod_group"].setObjectName("lodGroup")
|
||||
|
||||
# LOD列表
|
||||
self.controls["lod_list"] = QtWidgets.QListWidget()
|
||||
self.controls["lod_list"].setObjectName("lodList")
|
||||
|
||||
# LOD刷新按钮
|
||||
self.buttons["refresh_lod"] = QtWidgets.QPushButton(LANG.get("refresh", "刷新"))
|
||||
self.buttons["refresh_lod"].setObjectName("refreshLodButton")
|
||||
|
||||
# Meshes组
|
||||
self.controls["meshes_group"] = QtWidgets.QGroupBox(LANG.get("meshes_group", "几何体"))
|
||||
self.controls["meshes_group"].setObjectName("meshesGroup")
|
||||
|
||||
# Meshes列表
|
||||
self.controls["meshes_list"] = QtWidgets.QListWidget()
|
||||
self.controls["meshes_list"].setObjectName("meshesList")
|
||||
|
||||
# Meshes刷新按钮
|
||||
self.buttons["refresh_meshes"] = QtWidgets.QPushButton(LANG.get("refresh", "刷新"))
|
||||
self.buttons["refresh_meshes"].setObjectName("refreshMeshesButton")
|
||||
|
||||
# Joints组
|
||||
self.controls["joints_group"] = QtWidgets.QGroupBox(LANG.get("joints_group", "关节"))
|
||||
self.controls["joints_group"].setObjectName("jointsGroup")
|
||||
|
||||
# Joints列表
|
||||
self.controls["joints_list"] = QtWidgets.QListWidget()
|
||||
self.controls["joints_list"].setObjectName("jointsList")
|
||||
|
||||
# Joints刷新按钮
|
||||
self.buttons["refresh_joints"] = QtWidgets.QPushButton(LANG.get("refresh", "刷新"))
|
||||
self.buttons["refresh_joints"].setObjectName("refreshJointsButton")
|
||||
|
||||
# 右侧面板控件
|
||||
# 写入组
|
||||
self.controls["write_group"] = QtWidgets.QGroupBox(LANG.get("write_group", "写入"))
|
||||
self.controls["write_group"].setObjectName("writeGroup")
|
||||
|
||||
# 写入按钮
|
||||
self.buttons["write_joint_default"] = QtWidgets.QPushButton(LANG.get("write_joint_default", "写入关节默认位置"))
|
||||
self.buttons["write_geometry"] = QtWidgets.QPushButton(LANG.get("write_geometry", "写入几何体"))
|
||||
self.buttons["write_skinning"] = QtWidgets.QPushButton(LANG.get("write_skinning", "写入蒙皮"))
|
||||
self.buttons["write_blendshape"] = QtWidgets.QPushButton(LANG.get("write_blendshape", "写入混合变形目标"))
|
||||
|
||||
# 创建组
|
||||
self.controls["create_group"] = QtWidgets.QGroupBox(LANG.get("create_group", "创建"))
|
||||
self.controls["create_group"].setObjectName("createGroup")
|
||||
|
||||
# 创建按钮
|
||||
self.buttons["create_blendshape"] = QtWidgets.QPushButton(LANG.get("create_blendshape", "创建混合变形"))
|
||||
self.buttons["bind_skin"] = QtWidgets.QPushButton(LANG.get("bind_skin", "绑定蒙皮"))
|
||||
self.buttons["unbind_skin"] = QtWidgets.QPushButton(LANG.get("unbind_skin", "取消蒙皮"))
|
||||
|
||||
# 工具组
|
||||
self.controls["tools_group"] = QtWidgets.QGroupBox(LANG.get("tools_group", "工具"))
|
||||
self.controls["tools_group"].setObjectName("toolsGroup")
|
||||
|
||||
# 工具按钮
|
||||
self.buttons["reposition_head_joints"] = QtWidgets.QPushButton(LANG.get("reposition_head_joints", "重新定位头部关节"))
|
||||
self.buttons["reposition_body_joints"] = QtWidgets.QPushButton(LANG.get("reposition_body_joints", "重新定位身体关节"))
|
||||
self.buttons["reposition_all_joints"] = QtWidgets.QPushButton(LANG.get("reposition_all_joints", "重新定位全身关节"))
|
||||
self.buttons["quick_preset"] = QtWidgets.QPushButton(LANG.get("quick_preset", "快速创建预设"))
|
||||
|
||||
def widgets():
|
||||
"""
|
||||
创建定义系统UI控件
|
||||
"""
|
||||
global definition_tabs, dna_elements, definition_buttons
|
||||
|
||||
# 创建子标签页
|
||||
definition_tabs = QtWidgets.QTabWidget()
|
||||
|
||||
# 创建各类元素列表
|
||||
dna_elements["lod_list"] = QtWidgets.QListWidget()
|
||||
dna_elements["lod_list"].setObjectName("LodList")
|
||||
|
||||
dna_elements["mesh_list"] = QtWidgets.QListWidget()
|
||||
dna_elements["mesh_list"].setObjectName("MeshList")
|
||||
|
||||
dna_elements["joint_list"] = QtWidgets.QListWidget()
|
||||
dna_elements["joint_list"].setObjectName("JointList")
|
||||
|
||||
dna_elements["blendshape_list"] = QtWidgets.QListWidget()
|
||||
dna_elements["blendshape_list"].setObjectName("BlendshapeList")
|
||||
|
||||
dna_elements["animmap_list"] = QtWidgets.QListWidget()
|
||||
dna_elements["animmap_list"].setObjectName("AnimatedMapList")
|
||||
|
||||
# 创建元素信息面板
|
||||
dna_elements["element_info"] = QtWidgets.QTextEdit()
|
||||
dna_elements["element_info"].setReadOnly(True)
|
||||
dna_elements["element_info"].setObjectName("ElementInfo")
|
||||
|
||||
# 创建列表标题标签
|
||||
dna_elements["lod_label"] = QtWidgets.QLabel("LODs [000]")
|
||||
dna_elements["mesh_label"] = QtWidgets.QLabel("Meshes [000]")
|
||||
dna_elements["joint_label"] = QtWidgets.QLabel("Joints [000]")
|
||||
dna_elements["blendshape_label"] = QtWidgets.QLabel("BlendShapes [000]")
|
||||
dna_elements["animmap_label"] = QtWidgets.QLabel("AnimatedMap [000]")
|
||||
|
||||
# 创建刷新按钮
|
||||
dna_elements["refresh_lod"] = QtWidgets.QPushButton("刷新")
|
||||
dna_elements["refresh_lod"].setObjectName("RefreshButton")
|
||||
dna_elements["refresh_lod"].setFixedWidth(60)
|
||||
|
||||
dna_elements["refresh_mesh"] = QtWidgets.QPushButton("刷新")
|
||||
dna_elements["refresh_mesh"].setObjectName("RefreshButton")
|
||||
dna_elements["refresh_mesh"].setFixedWidth(60)
|
||||
|
||||
dna_elements["refresh_joint"] = QtWidgets.QPushButton("刷新")
|
||||
dna_elements["refresh_joint"].setObjectName("RefreshButton")
|
||||
dna_elements["refresh_joint"].setFixedWidth(60)
|
||||
|
||||
dna_elements["refresh_blendshape"] = QtWidgets.QPushButton("刷新")
|
||||
dna_elements["refresh_blendshape"].setObjectName("RefreshButton")
|
||||
dna_elements["refresh_blendshape"].setFixedWidth(60)
|
||||
|
||||
dna_elements["refresh_animmap"] = QtWidgets.QPushButton("刷新")
|
||||
dna_elements["refresh_animmap"].setObjectName("RefreshButton")
|
||||
dna_elements["refresh_animmap"].setFixedWidth(60)
|
||||
|
||||
# 创建LOD和Meshes特殊按钮
|
||||
dna_elements["define_lod_joint"] = QtWidgets.QPushButton("定义LOD关节")
|
||||
set_button_icon(dna_elements["define_lod_joint"], "layerEditor.png")
|
||||
dna_elements["define_lod_joint"].setMinimumHeight(28)
|
||||
dna_elements["define_lod_joint"].setStyleSheet("text-align: left; padding-left: 30px;")
|
||||
dna_elements["define_lod_joint"].setToolTip("定义LOD关节")
|
||||
|
||||
dna_elements["create_geometry"] = QtWidgets.QPushButton("创建几何体")
|
||||
set_button_icon(dna_elements["create_geometry"], "polyCube.png")
|
||||
dna_elements["create_geometry"].setMinimumHeight(28)
|
||||
dna_elements["create_geometry"].setStyleSheet("text-align: left; padding-left: 30px;")
|
||||
dna_elements["create_geometry"].setToolTip("创建几何体")
|
||||
|
||||
# 功能按钮
|
||||
# 写入组按钮
|
||||
definition_buttons["write_joint_defaults"] = QtWidgets.QPushButton("写入关节默认位置")
|
||||
set_button_icon(definition_buttons["write_joint_defaults"], "HIKCharacterToolBodyPart.png")
|
||||
|
||||
definition_buttons["write_geometry"] = QtWidgets.QPushButton("写入几何体")
|
||||
set_button_icon(definition_buttons["write_geometry"], "polyCube.png")
|
||||
|
||||
definition_buttons["write_skinning"] = QtWidgets.QPushButton("写入蒙皮权重")
|
||||
set_button_icon(definition_buttons["write_skinning"], "paintSkinWeights.png")
|
||||
|
||||
definition_buttons["write_blendshapes"] = QtWidgets.QPushButton("写入混合变形目标")
|
||||
set_button_icon(definition_buttons["write_blendshapes"], "blendShape.png")
|
||||
|
||||
# 创建组按钮
|
||||
definition_buttons["create_blendshapes"] = QtWidgets.QPushButton("创建混合变形")
|
||||
set_button_icon(definition_buttons["create_blendshapes"], "blendShapeEditor.png")
|
||||
|
||||
definition_buttons["bind_skin"] = QtWidgets.QPushButton("绑定蒙皮")
|
||||
set_button_icon(definition_buttons["bind_skin"], "smoothSkin.png")
|
||||
|
||||
definition_buttons["unbind_skin"] = QtWidgets.QPushButton("取消蒙皮")
|
||||
set_button_icon(definition_buttons["unbind_skin"], "detachSkin.png")
|
||||
|
||||
# 工具组按钮
|
||||
definition_buttons["reposition_head"] = QtWidgets.QPushButton("重新定位头部关节")
|
||||
set_button_icon(definition_buttons["reposition_head"], "HIKCharacterToolSkeleton.png")
|
||||
|
||||
definition_buttons["reposition_body"] = QtWidgets.QPushButton("重新定位身体关节")
|
||||
set_button_icon(definition_buttons["reposition_body"], "HIKCharacterToolSkeleton.png")
|
||||
|
||||
definition_buttons["reposition_all"] = QtWidgets.QPushButton("重新定位全身关节")
|
||||
set_button_icon(definition_buttons["reposition_all"], "HIKCharacterToolSkeleton.png")
|
||||
|
||||
definition_buttons["quick_preset"] = QtWidgets.QPushButton("快速创建预设")
|
||||
set_button_icon(definition_buttons["quick_preset"], "QR_QuickRigTool.png")
|
||||
|
||||
# 设置按钮样式
|
||||
for button in definition_buttons.values():
|
||||
button.setMinimumHeight(28)
|
||||
# 设置按钮文本对齐方式,使图标在左侧,文本在右侧
|
||||
button.setStyleSheet("text-align: left; padding-left: 30px;")
|
||||
# 设置工具提示与按钮文本相同
|
||||
button.setToolTip(button.text())
|
||||
#========================================= LAYOUT =======================================
|
||||
def create_layouts(self):
|
||||
"""
|
||||
创建定义系统UI布局
|
||||
组织控件的排列和层次结构
|
||||
"""
|
||||
# 主布局
|
||||
self.layouts["main_layout"] = QtWidgets.QVBoxLayout(self.main_widget)
|
||||
self.layouts["main_layout"].setContentsMargins(5, 5, 5, 5)
|
||||
self.layouts["main_layout"].setSpacing(5)
|
||||
|
||||
# 添加标题标签
|
||||
self.layouts["main_layout"].addWidget(self.controls["title_label"])
|
||||
|
||||
# 添加主分割器
|
||||
self.layouts["main_layout"].addWidget(self.splitters["main_splitter"])
|
||||
|
||||
# 将左右面板添加到主分割器
|
||||
self.splitters["main_splitter"].addWidget(self.controls["left_panel"])
|
||||
self.splitters["main_splitter"].addWidget(self.controls["right_panel"])
|
||||
|
||||
# 左侧面板布局
|
||||
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)
|
||||
|
||||
# LOD组布局
|
||||
self.layouts["lod_layout"] = QtWidgets.QVBoxLayout(self.controls["lod_group"])
|
||||
self.layouts["lod_layout"].addWidget(self.controls["lod_list"])
|
||||
self.layouts["lod_layout"].addWidget(self.buttons["refresh_lod"])
|
||||
|
||||
# Meshes组布局
|
||||
self.layouts["meshes_layout"] = QtWidgets.QVBoxLayout(self.controls["meshes_group"])
|
||||
self.layouts["meshes_layout"].addWidget(self.controls["meshes_list"])
|
||||
self.layouts["meshes_layout"].addWidget(self.buttons["refresh_meshes"])
|
||||
|
||||
# Joints组布局
|
||||
self.layouts["joints_layout"] = QtWidgets.QVBoxLayout(self.controls["joints_group"])
|
||||
self.layouts["joints_layout"].addWidget(self.controls["joints_list"])
|
||||
self.layouts["joints_layout"].addWidget(self.buttons["refresh_joints"])
|
||||
|
||||
# 添加组到左侧面板布局
|
||||
self.layouts["left_layout"].addWidget(self.controls["lod_group"])
|
||||
self.layouts["left_layout"].addWidget(self.controls["meshes_group"])
|
||||
self.layouts["left_layout"].addWidget(self.controls["joints_group"])
|
||||
self.layouts["left_layout"].addStretch()
|
||||
|
||||
# 右侧面板布局
|
||||
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["write_layout"] = QtWidgets.QVBoxLayout(self.controls["write_group"])
|
||||
self.layouts["write_layout"].addWidget(self.buttons["write_joint_default"])
|
||||
self.layouts["write_layout"].addWidget(self.buttons["write_geometry"])
|
||||
self.layouts["write_layout"].addWidget(self.buttons["write_skinning"])
|
||||
self.layouts["write_layout"].addWidget(self.buttons["write_blendshape"])
|
||||
|
||||
# 创建组布局
|
||||
self.layouts["create_layout"] = QtWidgets.QVBoxLayout(self.controls["create_group"])
|
||||
self.layouts["create_layout"].addWidget(self.buttons["create_blendshape"])
|
||||
self.layouts["create_layout"].addWidget(self.buttons["bind_skin"])
|
||||
self.layouts["create_layout"].addWidget(self.buttons["unbind_skin"])
|
||||
|
||||
# 工具组布局
|
||||
self.layouts["tools_layout"] = QtWidgets.QVBoxLayout(self.controls["tools_group"])
|
||||
self.layouts["tools_layout"].addWidget(self.buttons["reposition_head_joints"])
|
||||
self.layouts["tools_layout"].addWidget(self.buttons["reposition_body_joints"])
|
||||
self.layouts["tools_layout"].addWidget(self.buttons["reposition_all_joints"])
|
||||
self.layouts["tools_layout"].addWidget(self.buttons["quick_preset"])
|
||||
|
||||
# 添加组到右侧面板布局
|
||||
self.layouts["right_layout"].addWidget(self.controls["write_group"])
|
||||
self.layouts["right_layout"].addWidget(self.controls["create_group"])
|
||||
self.layouts["right_layout"].addWidget(self.controls["tools_group"])
|
||||
self.layouts["right_layout"].addStretch()
|
||||
|
||||
# 创建分割器大小处理器
|
||||
self.resize_handlers["main_splitter"] = ui_utils.SplitterResizeHandler(
|
||||
self.main_widget, self.splitters["main_splitter"], is_horizontal=True
|
||||
)
|
||||
|
||||
#========================================== LAYOUTS ==========================================
|
||||
def layouts(parent_tab=None):
|
||||
"""
|
||||
创建定义系统UI布局
|
||||
|
||||
Args:
|
||||
parent_tab: 父容器控件,由Main.py传入
|
||||
"""
|
||||
# 获取父容器(在Main.py中创建的definition_tab)
|
||||
if not parent_tab:
|
||||
parent_tab = ui_utils.get_parent_widget("definition_tab")
|
||||
if not parent_tab:
|
||||
print("无法获取父容器,布局创建失败")
|
||||
return
|
||||
|
||||
# 创建主布局
|
||||
main_layout = parent_tab.layout()
|
||||
if not main_layout:
|
||||
print("父容器没有布局,布局创建失败")
|
||||
return
|
||||
|
||||
# 创建主分割控件 - 水平分割
|
||||
main_splitter = QtWidgets.QSplitter(QtCore.Qt.Horizontal)
|
||||
|
||||
# 创建左侧区域 - 垂直分割
|
||||
left_splitter = QtWidgets.QSplitter(QtCore.Qt.Vertical)
|
||||
|
||||
# 创建LOD区域
|
||||
lod_widget = QtWidgets.QWidget()
|
||||
lod_layout = QtWidgets.QVBoxLayout(lod_widget)
|
||||
lod_layout.setContentsMargins(4, 4, 4, 4)
|
||||
lod_layout.setSpacing(4)
|
||||
|
||||
# LOD标题栏
|
||||
lod_header = QtWidgets.QWidget()
|
||||
lod_header_layout = QtWidgets.QHBoxLayout(lod_header)
|
||||
lod_header_layout.setContentsMargins(0, 0, 0, 0)
|
||||
lod_header_layout.addWidget(dna_elements["lod_label"])
|
||||
lod_header_layout.addStretch()
|
||||
lod_header_layout.addWidget(dna_elements["refresh_lod"])
|
||||
|
||||
lod_layout.addWidget(lod_header)
|
||||
lod_layout.addWidget(dna_elements["lod_list"])
|
||||
lod_layout.addWidget(dna_elements["define_lod_joint"])
|
||||
|
||||
# 创建Meshes区域
|
||||
mesh_widget = QtWidgets.QWidget()
|
||||
mesh_layout = QtWidgets.QVBoxLayout(mesh_widget)
|
||||
mesh_layout.setContentsMargins(4, 4, 4, 4)
|
||||
mesh_layout.setSpacing(4)
|
||||
|
||||
# Meshes标题栏
|
||||
mesh_header = QtWidgets.QWidget()
|
||||
mesh_header_layout = QtWidgets.QHBoxLayout(mesh_header)
|
||||
mesh_header_layout.setContentsMargins(0, 0, 0, 0)
|
||||
mesh_header_layout.addWidget(dna_elements["mesh_label"])
|
||||
mesh_header_layout.addStretch()
|
||||
mesh_header_layout.addWidget(dna_elements["refresh_mesh"])
|
||||
|
||||
mesh_layout.addWidget(mesh_header)
|
||||
mesh_layout.addWidget(dna_elements["mesh_list"])
|
||||
mesh_layout.addWidget(dna_elements["create_geometry"])
|
||||
|
||||
# 添加到左侧垂直分割控件
|
||||
left_splitter.addWidget(lod_widget)
|
||||
left_splitter.addWidget(mesh_widget)
|
||||
|
||||
# 创建右侧区域 - 垂直分割
|
||||
right_splitter = QtWidgets.QSplitter(QtCore.Qt.Vertical)
|
||||
|
||||
# 创建右上区域 - Joints
|
||||
right_top_widget = QtWidgets.QWidget()
|
||||
right_top_layout = QtWidgets.QVBoxLayout(right_top_widget)
|
||||
right_top_layout.setContentsMargins(4, 4, 4, 4)
|
||||
right_top_layout.setSpacing(4)
|
||||
|
||||
# Joints标题栏
|
||||
joint_header = QtWidgets.QWidget()
|
||||
joint_header_layout = QtWidgets.QHBoxLayout(joint_header)
|
||||
joint_header_layout.setContentsMargins(0, 0, 0, 0)
|
||||
joint_header_layout.addWidget(dna_elements["joint_label"])
|
||||
joint_header_layout.addStretch()
|
||||
joint_header_layout.addWidget(dna_elements["refresh_joint"])
|
||||
|
||||
right_top_layout.addWidget(joint_header)
|
||||
right_top_layout.addWidget(dna_elements["joint_list"])
|
||||
|
||||
# 创建右中区域 - BlendShapes
|
||||
right_middle_widget = QtWidgets.QWidget()
|
||||
right_middle_layout = QtWidgets.QVBoxLayout(right_middle_widget)
|
||||
right_middle_layout.setContentsMargins(4, 4, 4, 4)
|
||||
right_middle_layout.setSpacing(4)
|
||||
|
||||
# BlendShapes标题栏
|
||||
blendshape_header = QtWidgets.QWidget()
|
||||
blendshape_header_layout = QtWidgets.QHBoxLayout(blendshape_header)
|
||||
blendshape_header_layout.setContentsMargins(0, 0, 0, 0)
|
||||
blendshape_header_layout.addWidget(dna_elements["blendshape_label"])
|
||||
blendshape_header_layout.addStretch()
|
||||
blendshape_header_layout.addWidget(dna_elements["refresh_blendshape"])
|
||||
|
||||
right_middle_layout.addWidget(blendshape_header)
|
||||
right_middle_layout.addWidget(dna_elements["blendshape_list"])
|
||||
|
||||
# 创建右下区域 - AnimatedMap
|
||||
right_bottom_widget = QtWidgets.QWidget()
|
||||
right_bottom_layout = QtWidgets.QVBoxLayout(right_bottom_widget)
|
||||
right_bottom_layout.setContentsMargins(4, 4, 4, 4)
|
||||
right_bottom_layout.setSpacing(4)
|
||||
|
||||
# AnimatedMap标题栏
|
||||
animmap_header = QtWidgets.QWidget()
|
||||
animmap_header_layout = QtWidgets.QHBoxLayout(animmap_header)
|
||||
animmap_header_layout.setContentsMargins(0, 0, 0, 0)
|
||||
animmap_header_layout.addWidget(dna_elements["animmap_label"])
|
||||
animmap_header_layout.addStretch()
|
||||
animmap_header_layout.addWidget(dna_elements["refresh_animmap"])
|
||||
|
||||
right_bottom_layout.addWidget(animmap_header)
|
||||
right_bottom_layout.addWidget(dna_elements["animmap_list"])
|
||||
|
||||
# 添加到右侧分割控件
|
||||
right_splitter.addWidget(right_top_widget)
|
||||
right_splitter.addWidget(right_middle_widget)
|
||||
right_splitter.addWidget(right_bottom_widget)
|
||||
|
||||
# 设置右侧分割控件比例
|
||||
right_splitter.setSizes([200, 200, 200])
|
||||
|
||||
# 设置左侧分割控件比例 - 使其均等
|
||||
left_splitter.setSizes([300, 300])
|
||||
|
||||
# 设置左侧分割控件的伸缩因子,使两个模块均等分配空间
|
||||
left_splitter.setStretchFactor(0, 1) # LOD区域伸缩因子为1
|
||||
left_splitter.setStretchFactor(1, 1) # Meshes区域伸缩因子为1
|
||||
|
||||
# 添加到主分割控件
|
||||
main_splitter.addWidget(left_splitter)
|
||||
main_splitter.addWidget(right_splitter)
|
||||
|
||||
# 设置主分割控件比例 - 左右宽度相等
|
||||
main_splitter.setSizes([500, 500])
|
||||
|
||||
# 设置分割控件的伸缩因子,使其根据窗口大小均等分配空间
|
||||
main_splitter.setStretchFactor(0, 1) # 左侧伸缩因子为1
|
||||
main_splitter.setStretchFactor(1, 1) # 右侧伸缩因子为1
|
||||
|
||||
# 创建底部功能区域
|
||||
bottom_widget = QtWidgets.QWidget()
|
||||
bottom_layout = QtWidgets.QHBoxLayout(bottom_widget)
|
||||
bottom_layout.setContentsMargins(4, 4, 4, 4)
|
||||
|
||||
# 创建功能分组
|
||||
write_group = QtWidgets.QGroupBox("写入")
|
||||
write_layout = QtWidgets.QVBoxLayout(write_group)
|
||||
write_layout.setAlignment(QtCore.Qt.AlignTop) # 设置向顶部对齐
|
||||
write_layout.setContentsMargins(4, 8, 4, 4) # 减小内边距
|
||||
write_layout.setSpacing(4) # 减小间距
|
||||
write_layout.addWidget(definition_buttons["write_joint_defaults"])
|
||||
write_layout.addWidget(definition_buttons["write_geometry"])
|
||||
write_layout.addWidget(definition_buttons["write_skinning"])
|
||||
write_layout.addWidget(definition_buttons["write_blendshapes"])
|
||||
write_layout.addStretch() # 添加弹性空间,使按钮向顶部对齐
|
||||
|
||||
create_group = QtWidgets.QGroupBox("创建")
|
||||
create_layout = QtWidgets.QVBoxLayout(create_group)
|
||||
create_layout.setAlignment(QtCore.Qt.AlignTop) # 设置向顶部对齐
|
||||
create_layout.setContentsMargins(4, 8, 4, 4) # 减小内边距
|
||||
create_layout.setSpacing(4) # 减小间距
|
||||
create_layout.addWidget(definition_buttons["create_blendshapes"])
|
||||
create_layout.addWidget(definition_buttons["bind_skin"])
|
||||
create_layout.addWidget(definition_buttons["unbind_skin"])
|
||||
create_layout.addStretch() # 添加弹性空间,使按钮向顶部对齐
|
||||
|
||||
tools_group = QtWidgets.QGroupBox("工具")
|
||||
tools_layout = QtWidgets.QVBoxLayout(tools_group)
|
||||
tools_layout.setAlignment(QtCore.Qt.AlignTop) # 设置向顶部对齐
|
||||
tools_layout.setContentsMargins(4, 8, 4, 4) # 减小内边距
|
||||
tools_layout.setSpacing(4) # 减小间距
|
||||
tools_layout.addWidget(definition_buttons["reposition_head"])
|
||||
tools_layout.addWidget(definition_buttons["reposition_body"])
|
||||
tools_layout.addWidget(definition_buttons["reposition_all"])
|
||||
tools_layout.addWidget(definition_buttons["quick_preset"])
|
||||
tools_layout.addStretch() # 添加弹性空间,使按钮向顶部对齐
|
||||
|
||||
# 添加到底部布局
|
||||
bottom_layout.addWidget(write_group)
|
||||
bottom_layout.addWidget(create_group)
|
||||
bottom_layout.addWidget(tools_group)
|
||||
|
||||
# 创建主容器
|
||||
main_container = QtWidgets.QWidget()
|
||||
container_layout = QtWidgets.QVBoxLayout(main_container)
|
||||
container_layout.setContentsMargins(0, 0, 0, 0)
|
||||
container_layout.setSpacing(4)
|
||||
container_layout.addWidget(main_splitter, 1)
|
||||
container_layout.addWidget(bottom_widget, 0)
|
||||
|
||||
# 添加到主布局
|
||||
main_layout.addWidget(main_container)
|
||||
|
||||
#========================================== CONNECTIONS ==========================================
|
||||
def connections():
|
||||
"""
|
||||
连接定义系统UI信号和槽
|
||||
"""
|
||||
# 连接功能按钮点击事件
|
||||
definition_buttons["write_joint_defaults"].clicked.connect(lambda: print("写入关节默认位置功能待实现"))
|
||||
definition_buttons["write_geometry"].clicked.connect(lambda: print("写入几何体功能待实现"))
|
||||
definition_buttons["write_skinning"].clicked.connect(lambda: print("写入蒙皮功能待实现"))
|
||||
definition_buttons["write_blendshapes"].clicked.connect(lambda: print("写入混合变形目标功能待实现"))
|
||||
definition_buttons["create_blendshapes"].clicked.connect(lambda: print("创建混合变形功能待实现"))
|
||||
definition_buttons["bind_skin"].clicked.connect(lambda: print("绑定蒙皮功能待实现"))
|
||||
definition_buttons["unbind_skin"].clicked.connect(lambda: print("取消蒙皮功能待实现"))
|
||||
definition_buttons["reposition_head"].clicked.connect(lambda: print("重新定位头部关节功能待实现"))
|
||||
definition_buttons["reposition_body"].clicked.connect(lambda: print("重新定位身体关节功能待实现"))
|
||||
definition_buttons["reposition_all"].clicked.connect(lambda: print("重新定位全身关节功能待实现"))
|
||||
definition_buttons["quick_preset"].clicked.connect(lambda: print("快速创建预设功能待实现"))
|
||||
|
||||
# 连接列表选择事件
|
||||
for key, widget in dna_elements.items():
|
||||
if isinstance(widget, QtWidgets.QListWidget):
|
||||
widget.itemSelectionChanged.connect(lambda k=key: on_list_selection_changed(k))
|
||||
widget.itemDoubleClicked.connect(lambda item, k=key: on_list_item_double_clicked(item, k))
|
||||
|
||||
# 连接刷新按钮点击事件
|
||||
dna_elements["refresh_lod"].clicked.connect(lambda: refresh_list("lod_list"))
|
||||
dna_elements["refresh_mesh"].clicked.connect(lambda: refresh_list("mesh_list"))
|
||||
dna_elements["refresh_joint"].clicked.connect(lambda: refresh_list("joint_list"))
|
||||
dna_elements["refresh_blendshape"].clicked.connect(lambda: refresh_list("blendshape_list"))
|
||||
dna_elements["refresh_animmap"].clicked.connect(lambda: refresh_list("animmap_list"))
|
||||
|
||||
# 连接LOD和Meshes特殊按钮点击事件
|
||||
dna_elements["define_lod_joint"].clicked.connect(lambda: print("定义LOD关节功能待实现"))
|
||||
dna_elements["create_geometry"].clicked.connect(lambda: print("创建几何体功能待实现"))
|
||||
|
||||
# 列表选择变化处理函数
|
||||
def on_list_selection_changed(list_key):
|
||||
"""
|
||||
处理列表选择变化事件
|
||||
|
||||
Args:
|
||||
list_key: 列表键名
|
||||
"""
|
||||
selected_items = dna_elements[list_key].selectedItems()
|
||||
if selected_items:
|
||||
item = selected_items[0]
|
||||
info_text = f"选中的{list_key.split('_')[0]}: {item.text()}\n"
|
||||
info_text += f"\n属性信息将在此显示"
|
||||
dna_elements["element_info"].setText(info_text)
|
||||
print(f"{list_key} 选中项: {item.text()}")
|
||||
|
||||
# 列表项双击处理函数
|
||||
def on_list_item_double_clicked(item, list_key):
|
||||
"""
|
||||
处理列表项双击事件
|
||||
|
||||
Args:
|
||||
item: 被双击的列表项
|
||||
list_key: 列表键名
|
||||
"""
|
||||
print(f"{list_key} 双击项: {item.text()}")
|
||||
|
||||
# 刷新列表函数
|
||||
def refresh_list(list_key):
|
||||
"""
|
||||
刷新指定列表
|
||||
|
||||
Args:
|
||||
list_key: 要刷新的列表键名
|
||||
"""
|
||||
list_widget = dna_elements[list_key]
|
||||
list_widget.clear()
|
||||
|
||||
# 模拟数据加载
|
||||
test_data = {
|
||||
"lod_list": ["LOD_0", "LOD_1", "LOD_2"],
|
||||
"mesh_list": ["Head", "Body", "Eyes", "Teeth", "Tongue"],
|
||||
"joint_list": ["Head_Joint", "Neck_Joint", "Spine_Joint", "Arm_L_Joint", "Arm_R_Joint"],
|
||||
"blendshape_list": ["Smile", "Frown", "Blink", "Jaw_Open", "Brow_Raise"],
|
||||
"animmap_list": ["FaceMap_01", "BodyMap_01", "ExpressionMap_01"]
|
||||
}
|
||||
|
||||
# 添加测试数据到列表
|
||||
if list_key in test_data:
|
||||
for item in test_data[list_key]:
|
||||
list_widget.addItem(item)
|
||||
|
||||
# 更新对应标签的计数
|
||||
label_key = list_key.replace("list", "label")
|
||||
if label_key in dna_elements:
|
||||
count = list_widget.count()
|
||||
label_text = f"{label_key.split('_')[0].capitalize()}s [{count:03d}]"
|
||||
dna_elements[label_key].setText(label_text)
|
||||
|
||||
print(f"刷新{list_key}完成")
|
||||
|
||||
#===================================== PLACEHOLDER FUNCTION ===================================
|
||||
def definition_temp_function():
|
||||
utils_definition.definition_temp_utils_function
|
||||
#======================================= CONNECTION =====================================
|
||||
def create_connections(self):
|
||||
"""
|
||||
连接信号和槽
|
||||
设置UI控件的交互行为
|
||||
"""
|
||||
# 刷新按钮连接
|
||||
self.buttons["refresh_lod"].clicked.connect(utils_definition.definition_temp_utils_function)
|
||||
self.buttons["refresh_meshes"].clicked.connect(utils_definition.definition_temp_utils_function)
|
||||
self.buttons["refresh_joints"].clicked.connect(utils_definition.definition_temp_utils_function)
|
||||
|
||||
# 写入按钮连接
|
||||
self.buttons["write_joint_default"].clicked.connect(utils_definition.definition_temp_utils_function)
|
||||
self.buttons["write_geometry"].clicked.connect(utils_definition.definition_temp_utils_function)
|
||||
self.buttons["write_skinning"].clicked.connect(utils_definition.definition_temp_utils_function)
|
||||
self.buttons["write_blendshape"].clicked.connect(utils_definition.definition_temp_utils_function)
|
||||
|
||||
# 创建按钮连接
|
||||
self.buttons["create_blendshape"].clicked.connect(utils_definition.definition_temp_utils_function)
|
||||
self.buttons["bind_skin"].clicked.connect(utils_definition.definition_temp_utils_function)
|
||||
self.buttons["unbind_skin"].clicked.connect(utils_definition.definition_temp_utils_function)
|
||||
|
||||
# 工具按钮连接
|
||||
self.buttons["reposition_head_joints"].clicked.connect(utils_definition.definition_temp_utils_function)
|
||||
self.buttons["reposition_body_joints"].clicked.connect(utils_definition.definition_temp_utils_function)
|
||||
self.buttons["reposition_all_joints"].clicked.connect(utils_definition.definition_temp_utils_function)
|
||||
self.buttons["quick_preset"].clicked.connect(utils_definition.definition_temp_utils_function)
|
@@ -11,159 +11,232 @@ Geometry UI Module for Plugin
|
||||
- 自动加载模型
|
||||
- 标准化命名
|
||||
- 自动分组
|
||||
- 生成面部配件(睫毛,舌头,泪腺 等)
|
||||
- 生成面部配件(睑毛,舌头,泪腺 等)
|
||||
- 修复接缝(修复法线)
|
||||
- 修复点序
|
||||
"""
|
||||
|
||||
#===================================== IMPORT MODULES =====================================
|
||||
#========================================= 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
|
||||
|
||||
#===================================== IMPORT FUNCTIONS ===================================
|
||||
from scripts.utils import utils_geometry as utils_geometry
|
||||
from scripts.ui import ui_utils
|
||||
from scripts.utils import utils_geometry
|
||||
#========================================== 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
|
||||
|
||||
#========================================== WIDGETS ==========================================
|
||||
# 全局变量存储UI控件
|
||||
model_tree = None
|
||||
lod_combo = None
|
||||
model_buttons = {}
|
||||
model_info_panel = None
|
||||
class GeometryUI(ui_utils.BaseUI):
|
||||
"""
|
||||
几何模型UI类 - 负责显示几何模型编辑界面和基础操作
|
||||
继承自BaseUI类,实现几何模型相关的UI功能
|
||||
"""
|
||||
#========================================== INIT ========================================
|
||||
def __init__(self):
|
||||
"""
|
||||
初始化几何模型UI
|
||||
创建主控件和布局,并连接信号和槽
|
||||
"""
|
||||
super(GeometryUI, self).__init__()
|
||||
|
||||
# 创建主控件
|
||||
self.main_widget = QtWidgets.QWidget()
|
||||
self.main_widget.setObjectName("geometryMainWidget")
|
||||
|
||||
# 初始化UI
|
||||
self.create_widgets()
|
||||
self.create_layouts()
|
||||
self.create_connections()
|
||||
|
||||
def widgets():
|
||||
"""
|
||||
创建几何模型UI控件
|
||||
"""
|
||||
global model_tree, lod_combo, model_buttons, model_info_panel
|
||||
|
||||
# LOD选择下拉菜单
|
||||
lod_combo = QtWidgets.QComboBox()
|
||||
lod_combo.addItems(["LOD0", "LOD1", "LOD2", "LOD3", "LOD4"])
|
||||
lod_combo.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
lod_combo.setMinimumWidth(100)
|
||||
|
||||
# 模型树形视图
|
||||
model_tree = QtWidgets.QTreeWidget()
|
||||
model_tree.setHeaderLabels(["模型名称", "顶点数", "面数"])
|
||||
model_tree.setMinimumHeight(250)
|
||||
model_tree.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
|
||||
model_tree.header().setSectionResizeMode(QtWidgets.QHeaderView.Stretch) # 列自动拉伸
|
||||
|
||||
# 模型信息面板
|
||||
model_info_panel = QtWidgets.QTextEdit()
|
||||
model_info_panel.setReadOnly(True)
|
||||
model_info_panel.setMinimumHeight(100)
|
||||
model_info_panel.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
|
||||
|
||||
# 功能按钮 - 设置统一的大小策略
|
||||
for button_name in ["load_model", "create_lod", "auto_load", "standardize_name",
|
||||
"auto_group", "generate_accessories", "fix_seams", "fix_vertex_order"]:
|
||||
model_buttons[button_name] = QtWidgets.QPushButton({
|
||||
"load_model": "加载模型",
|
||||
"create_lod": "创建LOD",
|
||||
"auto_load": "自动加载",
|
||||
"standardize_name": "标准化命名",
|
||||
"auto_group": "自动分组",
|
||||
"generate_accessories": "生成面部配件",
|
||||
"fix_seams": "修复接缝",
|
||||
"fix_vertex_order": "修复点序"
|
||||
}[button_name])
|
||||
model_buttons[button_name].setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
model_buttons[button_name].setMinimumWidth(120)
|
||||
#========================================= WIDGET =======================================
|
||||
def create_widgets(self):
|
||||
"""
|
||||
创建几何模型UI控件
|
||||
包括按钮、标签、列表等
|
||||
"""
|
||||
# 标题标签
|
||||
self.controls["title_label"] = QtWidgets.QLabel(LANG.get("geometry_title", "几何模型"))
|
||||
self.controls["title_label"].setObjectName("geometryTitleLabel")
|
||||
self.controls["title_label"].setAlignment(QtCore.Qt.AlignCenter)
|
||||
|
||||
# 创建主分割器
|
||||
self.splitters["main_splitter"] = QtWidgets.QSplitter(QtCore.Qt.Horizontal)
|
||||
self.splitters["main_splitter"].setObjectName("geometryMainSplitter")
|
||||
|
||||
# 左侧面板
|
||||
self.controls["left_panel"] = QtWidgets.QWidget()
|
||||
self.controls["left_panel"].setObjectName("geometryLeftPanel")
|
||||
|
||||
# 右侧面板
|
||||
self.controls["right_panel"] = QtWidgets.QWidget()
|
||||
self.controls["right_panel"].setObjectName("geometryRightPanel")
|
||||
|
||||
# 左侧面板控件
|
||||
# 模型列表组
|
||||
self.controls["model_group"] = QtWidgets.QGroupBox(LANG.get("model_group", "模型列表"))
|
||||
self.controls["model_group"].setObjectName("modelGroup")
|
||||
|
||||
# 模型列表
|
||||
self.controls["model_list"] = QtWidgets.QListWidget()
|
||||
self.controls["model_list"].setObjectName("modelList")
|
||||
|
||||
# 模型刷新按钮
|
||||
self.buttons["refresh_models"] = QtWidgets.QPushButton(LANG.get("refresh", "刷新"))
|
||||
self.buttons["refresh_models"].setObjectName("refreshModelsButton")
|
||||
|
||||
# LOD过滤组
|
||||
self.controls["lod_filter_group"] = QtWidgets.QGroupBox(LANG.get("lod_filter_group", "LOD过滤"))
|
||||
self.controls["lod_filter_group"].setObjectName("lodFilterGroup")
|
||||
|
||||
# LOD选择
|
||||
self.controls["lod_label"] = QtWidgets.QLabel(LANG.get("lod", "LOD:"))
|
||||
self.controls["lod_combo"] = QtWidgets.QComboBox()
|
||||
self.controls["lod_combo"].setObjectName("lodCombo")
|
||||
|
||||
# 右侧面板控件
|
||||
# 模型操作组
|
||||
self.controls["model_ops_group"] = QtWidgets.QGroupBox(LANG.get("model_operations", "模型操作"))
|
||||
self.controls["model_ops_group"].setObjectName("modelOpsGroup")
|
||||
|
||||
# 模型操作按钮
|
||||
self.buttons["pick_model"] = QtWidgets.QPushButton(LANG.get("pick_model", "拾取模型"))
|
||||
self.buttons["load_model"] = QtWidgets.QPushButton(LANG.get("load_model", "加载模型"))
|
||||
self.buttons["create_lod"] = QtWidgets.QPushButton(LANG.get("create_lod", "创建LOD"))
|
||||
self.buttons["auto_load"] = QtWidgets.QPushButton(LANG.get("auto_load", "自动加载"))
|
||||
|
||||
# 模型工具组
|
||||
self.controls["model_tools_group"] = QtWidgets.QGroupBox(LANG.get("model_tools", "模型工具"))
|
||||
self.controls["model_tools_group"].setObjectName("modelToolsGroup")
|
||||
|
||||
# 模型工具按钮
|
||||
self.buttons["standardize_names"] = QtWidgets.QPushButton(LANG.get("standardize_names", "标准化命名"))
|
||||
self.buttons["auto_group"] = QtWidgets.QPushButton(LANG.get("auto_group", "自动分组"))
|
||||
self.buttons["generate_accessories"] = QtWidgets.QPushButton(LANG.get("generate_accessories", "生成面部配件"))
|
||||
self.buttons["fix_seams"] = QtWidgets.QPushButton(LANG.get("fix_seams", "修复接缝"))
|
||||
self.buttons["fix_vertex_order"] = QtWidgets.QPushButton(LANG.get("fix_vertex_order", "修复点序"))
|
||||
|
||||
#========================================== LAYOUTS ==========================================
|
||||
def layouts(parent_tab=None):
|
||||
"""
|
||||
创建几何模型UI布局
|
||||
|
||||
Args:
|
||||
parent_tab: 父容器控件,由Main.py传入
|
||||
"""
|
||||
# 获取父容器(在Main.py中创建的geometry_tab)
|
||||
if not parent_tab:
|
||||
parent_tab = ui_utils.get_parent_widget("geometry_tab")
|
||||
if not parent_tab:
|
||||
print("无法获取父容器,布局创建失败")
|
||||
return
|
||||
|
||||
# 创建主布局
|
||||
main_layout = parent_tab.layout()
|
||||
if not main_layout:
|
||||
main_layout = QtWidgets.QVBoxLayout(parent_tab)
|
||||
main_layout.setContentsMargins(4, 4, 4, 4)
|
||||
main_layout.setSpacing(4)
|
||||
main_layout.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint) # 设置布局约束为默认,允许自适应
|
||||
|
||||
# 创建分割控件
|
||||
splitter = QtWidgets.QSplitter(QtCore.Qt.Vertical)
|
||||
|
||||
# 上部区域 - LOD选择和模型树
|
||||
top_widget = QtWidgets.QWidget()
|
||||
top_layout = QtWidgets.QVBoxLayout(top_widget)
|
||||
top_layout.setContentsMargins(0, 0, 0, 0)
|
||||
|
||||
# LOD选择区域
|
||||
lod_layout = QtWidgets.QHBoxLayout()
|
||||
lod_layout.addWidget(QtWidgets.QLabel("LOD级别:"))
|
||||
lod_layout.addWidget(lod_combo)
|
||||
lod_layout.addStretch()
|
||||
top_layout.addLayout(lod_layout)
|
||||
|
||||
# 模型树区域
|
||||
model_group = QtWidgets.QGroupBox("模型列表")
|
||||
model_layout = QtWidgets.QVBoxLayout(model_group)
|
||||
model_layout.addWidget(model_tree)
|
||||
top_layout.addWidget(model_group)
|
||||
|
||||
# 下部区域 - 模型信息
|
||||
model_info_group = QtWidgets.QGroupBox("模型信息")
|
||||
model_info_layout = QtWidgets.QVBoxLayout(model_info_group)
|
||||
model_info_layout.addWidget(model_info_panel)
|
||||
|
||||
# 添加到分割控件
|
||||
splitter.addWidget(top_widget)
|
||||
splitter.addWidget(model_info_group)
|
||||
|
||||
# 按钮区域
|
||||
button_layout = QtWidgets.QGridLayout()
|
||||
button_layout.addWidget(model_buttons["load_model"], 0, 0)
|
||||
button_layout.addWidget(model_buttons["create_lod"], 0, 1)
|
||||
button_layout.addWidget(model_buttons["auto_load"], 1, 0)
|
||||
button_layout.addWidget(model_buttons["standardize_name"], 1, 1)
|
||||
button_layout.addWidget(model_buttons["auto_group"], 2, 0)
|
||||
button_layout.addWidget(model_buttons["generate_accessories"], 2, 1)
|
||||
button_layout.addWidget(model_buttons["fix_seams"], 3, 0)
|
||||
button_layout.addWidget(model_buttons["fix_vertex_order"], 3, 1)
|
||||
|
||||
# 添加到主布局
|
||||
main_layout.addWidget(splitter)
|
||||
main_layout.addLayout(button_layout)
|
||||
#========================================= LAYOUT =======================================
|
||||
def create_layouts(self):
|
||||
"""
|
||||
创建几何模型UI布局
|
||||
组织控件的排列和层次结构
|
||||
"""
|
||||
# 主布局
|
||||
self.layouts["main_layout"] = QtWidgets.QVBoxLayout(self.main_widget)
|
||||
self.layouts["main_layout"].setContentsMargins(5, 5, 5, 5)
|
||||
self.layouts["main_layout"].setSpacing(5)
|
||||
|
||||
# 添加标题标签
|
||||
self.layouts["main_layout"].addWidget(self.controls["title_label"])
|
||||
|
||||
# 添加主分割器
|
||||
self.layouts["main_layout"].addWidget(self.splitters["main_splitter"])
|
||||
|
||||
# 将左右面板添加到主分割器
|
||||
self.splitters["main_splitter"].addWidget(self.controls["left_panel"])
|
||||
self.splitters["main_splitter"].addWidget(self.controls["right_panel"])
|
||||
|
||||
# 左侧面板布局
|
||||
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["model_list_layout"] = QtWidgets.QVBoxLayout(self.controls["model_group"])
|
||||
self.layouts["model_list_layout"].addWidget(self.controls["model_list"])
|
||||
self.layouts["model_list_layout"].addWidget(self.buttons["refresh_models"])
|
||||
|
||||
# LOD过滤组布局
|
||||
self.layouts["lod_filter_layout"] = QtWidgets.QHBoxLayout(self.controls["lod_filter_group"])
|
||||
self.layouts["lod_filter_layout"].addWidget(self.controls["lod_label"])
|
||||
self.layouts["lod_filter_layout"].addWidget(self.controls["lod_combo"])
|
||||
|
||||
# 添加组到左侧面板布局
|
||||
self.layouts["left_layout"].addWidget(self.controls["model_group"])
|
||||
self.layouts["left_layout"].addWidget(self.controls["lod_filter_group"])
|
||||
self.layouts["left_layout"].addStretch()
|
||||
|
||||
# 右侧面板布局
|
||||
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["model_ops_layout"] = QtWidgets.QVBoxLayout(self.controls["model_ops_group"])
|
||||
self.layouts["model_ops_layout"].addWidget(self.buttons["pick_model"])
|
||||
self.layouts["model_ops_layout"].addWidget(self.buttons["load_model"])
|
||||
self.layouts["model_ops_layout"].addWidget(self.buttons["create_lod"])
|
||||
self.layouts["model_ops_layout"].addWidget(self.buttons["auto_load"])
|
||||
|
||||
# 模型工具组布局
|
||||
self.layouts["model_tools_layout"] = QtWidgets.QVBoxLayout(self.controls["model_tools_group"])
|
||||
self.layouts["model_tools_layout"].addWidget(self.buttons["standardize_names"])
|
||||
self.layouts["model_tools_layout"].addWidget(self.buttons["auto_group"])
|
||||
self.layouts["model_tools_layout"].addWidget(self.buttons["generate_accessories"])
|
||||
self.layouts["model_tools_layout"].addWidget(self.buttons["fix_seams"])
|
||||
self.layouts["model_tools_layout"].addWidget(self.buttons["fix_vertex_order"])
|
||||
|
||||
# 添加组到右侧面板布局
|
||||
self.layouts["right_layout"].addWidget(self.controls["model_ops_group"])
|
||||
self.layouts["right_layout"].addWidget(self.controls["model_tools_group"])
|
||||
self.layouts["right_layout"].addStretch()
|
||||
|
||||
# 创建分割器大小处理器
|
||||
self.resize_handlers["main_splitter"] = ui_utils.SplitterResizeHandler(
|
||||
self.main_widget, self.splitters["main_splitter"], is_horizontal=True
|
||||
)
|
||||
|
||||
#========================================== CONNECTIONS ==========================================
|
||||
def connections():
|
||||
"""
|
||||
连接几何模型UI信号和槽
|
||||
"""
|
||||
# 连接按钮点击事件到占位函数
|
||||
model_buttons["load_model"].clicked.connect(lambda: print("加载模型功能待实现"))
|
||||
model_buttons["create_lod"].clicked.connect(lambda: print("创建LOD功能待实现"))
|
||||
model_buttons["auto_load"].clicked.connect(lambda: print("自动加载功能待实现"))
|
||||
model_buttons["standardize_name"].clicked.connect(lambda: print("标准化命名功能待实现"))
|
||||
model_buttons["auto_group"].clicked.connect(lambda: print("自动分组功能待实现"))
|
||||
model_buttons["generate_accessories"].clicked.connect(lambda: print("生成面部配件功能待实现"))
|
||||
model_buttons["fix_seams"].clicked.connect(lambda: print("修复接缝功能待实现"))
|
||||
model_buttons["fix_vertex_order"].clicked.connect(lambda: print("修复点序功能待实现"))
|
||||
|
||||
# 连接LOD选择事件
|
||||
lod_combo.currentIndexChanged.connect(lambda index: print(f"选择的LOD级别: {lod_combo.currentText()}"))
|
||||
|
||||
# 连接模型树选择事件
|
||||
model_tree.itemSelectionChanged.connect(lambda: print("模型选择已更改"))
|
||||
|
||||
#===================================== PLACEHOLDER FUNCTION ===================================
|
||||
def geometry_temp_function():
|
||||
return utils_geometry.geometry_temp_utils_function()
|
||||
#======================================= CONNECTION =====================================
|
||||
def create_connections(self):
|
||||
"""
|
||||
连接信号和槽
|
||||
设置UI控件的交互行为
|
||||
"""
|
||||
# 模型列表按钮连接
|
||||
self.buttons["refresh_models"].clicked.connect(utils_geometry.geometry_temp_utils_function)
|
||||
|
||||
# LOD过滤连接
|
||||
self.controls["lod_combo"].currentIndexChanged.connect(utils_geometry.geometry_temp_utils_function)
|
||||
|
||||
# 模型操作按钮连接
|
||||
self.buttons["pick_model"].clicked.connect(utils_geometry.geometry_temp_utils_function)
|
||||
self.buttons["load_model"].clicked.connect(utils_geometry.geometry_temp_utils_function)
|
||||
self.buttons["create_lod"].clicked.connect(utils_geometry.geometry_temp_utils_function)
|
||||
self.buttons["auto_load"].clicked.connect(utils_geometry.geometry_temp_utils_function)
|
||||
|
||||
# 模型工具按钮连接
|
||||
self.buttons["standardize_names"].clicked.connect(utils_geometry.geometry_temp_utils_function)
|
||||
self.buttons["auto_group"].clicked.connect(utils_geometry.geometry_temp_utils_function)
|
||||
self.buttons["generate_accessories"].clicked.connect(utils_geometry.geometry_temp_utils_function)
|
||||
self.buttons["fix_seams"].clicked.connect(utils_geometry.geometry_temp_utils_function)
|
||||
self.buttons["fix_vertex_order"].clicked.connect(utils_geometry.geometry_temp_utils_function)
|
@@ -13,135 +13,201 @@ Rigging UI Module for Plugin
|
||||
- 创建绑定
|
||||
- 复制蒙皮
|
||||
"""
|
||||
|
||||
#===================================== IMPORT MODULES =====================================
|
||||
#========================================= 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
|
||||
|
||||
#===================================== IMPORT FUNCTIONS ===================================
|
||||
from scripts.utils import utils_rigging as utils_rigging
|
||||
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
|
||||
|
||||
#========================================== WIDGETS ==========================================
|
||||
# 全局变量存储UI控件
|
||||
dna_browser_tree = None
|
||||
joint_list = None
|
||||
dna_info_panel = None
|
||||
rig_buttons = {}
|
||||
class RiggingUI(ui_utils.BaseUI):
|
||||
"""
|
||||
绑定系统UI类 - 负责显示骨骼绑定编辑界面和基础操作
|
||||
继承自BaseUI类,实现绑定系统相关的UI功能
|
||||
"""
|
||||
#========================================== 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()
|
||||
|
||||
def widgets():
|
||||
"""
|
||||
创建绑定系统UI控件
|
||||
"""
|
||||
global dna_browser_tree, joint_list, dna_info_panel, rig_buttons
|
||||
|
||||
# DNA浏览器树形视图
|
||||
dna_browser_tree = QtWidgets.QTreeWidget()
|
||||
dna_browser_tree.setHeaderLabels(["DNA文件", "版本", "修改日期"])
|
||||
dna_browser_tree.setMinimumHeight(200)
|
||||
|
||||
# 关节列表
|
||||
joint_list = QtWidgets.QListWidget()
|
||||
joint_list.setMinimumHeight(150)
|
||||
|
||||
# DNA信息面板
|
||||
dna_info_panel = QtWidgets.QTextEdit()
|
||||
dna_info_panel.setReadOnly(True)
|
||||
dna_info_panel.setMinimumHeight(100)
|
||||
|
||||
# 功能按钮
|
||||
rig_buttons["load_dna"] = QtWidgets.QPushButton("加载DNA")
|
||||
rig_buttons["import_joints"] = QtWidgets.QPushButton("导入骨骼")
|
||||
rig_buttons["generate_body"] = QtWidgets.QPushButton("生成身体")
|
||||
rig_buttons["calibrate_dna"] = QtWidgets.QPushButton("DNA校准")
|
||||
rig_buttons["calibrate_joints"] = QtWidgets.QPushButton("骨骼位置校准")
|
||||
rig_buttons["create_binding"] = QtWidgets.QPushButton("创建绑定")
|
||||
rig_buttons["copy_skinning"] = QtWidgets.QPushButton("复制蒙皮")
|
||||
rig_buttons["save_dna"] = QtWidgets.QPushButton("保存DNA")
|
||||
#========================================= WIDGET =======================================
|
||||
def create_widgets(self):
|
||||
"""
|
||||
创建绑定系统UI控件
|
||||
包括按钮、标签、列表等
|
||||
"""
|
||||
# 标题标签
|
||||
self.controls["title_label"] = QtWidgets.QLabel(LANG.get("rigging_title", "骨骼绑定"))
|
||||
self.controls["title_label"].setObjectName("riggingTitleLabel")
|
||||
self.controls["title_label"].setAlignment(QtCore.Qt.AlignCenter)
|
||||
|
||||
# 创建主分割器
|
||||
self.splitters["main_splitter"] = QtWidgets.QSplitter(QtCore.Qt.Horizontal)
|
||||
self.splitters["main_splitter"].setObjectName("riggingMainSplitter")
|
||||
|
||||
# 左侧面板
|
||||
self.controls["left_panel"] = QtWidgets.QWidget()
|
||||
self.controls["left_panel"].setObjectName("riggingLeftPanel")
|
||||
|
||||
# 右侧面板
|
||||
self.controls["right_panel"] = QtWidgets.QWidget()
|
||||
self.controls["right_panel"].setObjectName("riggingRightPanel")
|
||||
|
||||
# 左侧面板控件
|
||||
# DNA浏览器组
|
||||
self.controls["dna_browser_group"] = QtWidgets.QGroupBox(LANG.get("dna_browser", "DNA浏览器"))
|
||||
self.controls["dna_browser_group"].setObjectName("dnaBrowserGroup")
|
||||
|
||||
# DNA浏览器列表
|
||||
self.controls["dna_list"] = QtWidgets.QListWidget()
|
||||
self.controls["dna_list"].setObjectName("dnaList")
|
||||
|
||||
# DNA浏览器刷新按钮
|
||||
self.buttons["refresh_dna"] = QtWidgets.QPushButton(LANG.get("refresh", "刷新"))
|
||||
self.buttons["refresh_dna"].setObjectName("refreshDnaButton")
|
||||
|
||||
# 右侧面板控件
|
||||
# DNA操作组
|
||||
self.controls["dna_ops_group"] = QtWidgets.QGroupBox(LANG.get("dna_operations", "DNA操作"))
|
||||
self.controls["dna_ops_group"].setObjectName("dnaOpsGroup")
|
||||
|
||||
# DNA操作按钮
|
||||
self.buttons["import_skeleton"] = QtWidgets.QPushButton(LANG.get("import_skeleton", "导入骨骼"))
|
||||
self.buttons["generate_body"] = QtWidgets.QPushButton(LANG.get("generate_body", "生成身体"))
|
||||
self.buttons["calibrate_dna"] = QtWidgets.QPushButton(LANG.get("calibrate_dna", "DNA校准"))
|
||||
|
||||
# 骨骼操作组
|
||||
self.controls["skeleton_ops_group"] = QtWidgets.QGroupBox(LANG.get("skeleton_operations", "骨骼操作"))
|
||||
self.controls["skeleton_ops_group"].setObjectName("skeletonOpsGroup")
|
||||
|
||||
# 骨骼操作按钮
|
||||
self.buttons["calibrate_skeleton"] = QtWidgets.QPushButton(LANG.get("calibrate_skeleton", "骨骼位置校准"))
|
||||
self.buttons["create_binding"] = QtWidgets.QPushButton(LANG.get("create_binding", "创建绑定"))
|
||||
self.buttons["copy_skin"] = QtWidgets.QPushButton(LANG.get("copy_skin", "复制蒙皮"))
|
||||
|
||||
#========================================== LAYOUTS ==========================================
|
||||
def layouts(parent_tab=None):
|
||||
"""
|
||||
创建绑定系统UI布局
|
||||
|
||||
Args:
|
||||
parent_tab: 父容器控件,由Main.py传入
|
||||
"""
|
||||
# 获取父容器(在Main.py中创建的rigging_tab)
|
||||
if not parent_tab:
|
||||
parent_tab = ui_utils.get_parent_widget("rigging_tab")
|
||||
if not parent_tab:
|
||||
print("无法获取父容器,布局创建失败")
|
||||
return
|
||||
|
||||
# 创建主布局
|
||||
main_layout = parent_tab.layout()
|
||||
if not main_layout:
|
||||
print("父容器没有布局,布局创建失败")
|
||||
return
|
||||
|
||||
# 创建分割控件
|
||||
splitter = QtWidgets.QSplitter(QtCore.Qt.Vertical)
|
||||
|
||||
# 上部区域 - DNA浏览器
|
||||
dna_browser_group = QtWidgets.QGroupBox("DNA浏览器")
|
||||
dna_browser_layout = QtWidgets.QVBoxLayout(dna_browser_group)
|
||||
dna_browser_layout.addWidget(dna_browser_tree)
|
||||
|
||||
# 中部区域 - 关节列表
|
||||
joint_list_group = QtWidgets.QGroupBox("骨骼列表")
|
||||
joint_list_layout = QtWidgets.QVBoxLayout(joint_list_group)
|
||||
joint_list_layout.addWidget(joint_list)
|
||||
|
||||
# 下部区域 - DNA信息
|
||||
dna_info_group = QtWidgets.QGroupBox("DNA信息")
|
||||
dna_info_layout = QtWidgets.QVBoxLayout(dna_info_group)
|
||||
dna_info_layout.addWidget(dna_info_panel)
|
||||
|
||||
# 添加到分割控件
|
||||
splitter.addWidget(dna_browser_group)
|
||||
splitter.addWidget(joint_list_group)
|
||||
splitter.addWidget(dna_info_group)
|
||||
|
||||
# 按钮区域
|
||||
button_layout = QtWidgets.QGridLayout()
|
||||
button_layout.addWidget(rig_buttons["load_dna"], 0, 0)
|
||||
button_layout.addWidget(rig_buttons["import_joints"], 0, 1)
|
||||
button_layout.addWidget(rig_buttons["generate_body"], 1, 0)
|
||||
button_layout.addWidget(rig_buttons["calibrate_dna"], 1, 1)
|
||||
button_layout.addWidget(rig_buttons["calibrate_joints"], 2, 0)
|
||||
button_layout.addWidget(rig_buttons["create_binding"], 2, 1)
|
||||
button_layout.addWidget(rig_buttons["copy_skinning"], 3, 0)
|
||||
button_layout.addWidget(rig_buttons["save_dna"], 3, 1)
|
||||
|
||||
# 添加到主布局
|
||||
main_layout.addWidget(splitter)
|
||||
main_layout.addLayout(button_layout)
|
||||
#========================================= LAYOUT =======================================
|
||||
def create_layouts(self):
|
||||
"""
|
||||
创建绑定系统UI布局
|
||||
组织控件的排列和层次结构
|
||||
"""
|
||||
# 主布局
|
||||
self.layouts["main_layout"] = QtWidgets.QVBoxLayout(self.main_widget)
|
||||
self.layouts["main_layout"].setContentsMargins(5, 5, 5, 5)
|
||||
self.layouts["main_layout"].setSpacing(5)
|
||||
|
||||
# 添加标题标签
|
||||
self.layouts["main_layout"].addWidget(self.controls["title_label"])
|
||||
|
||||
# 添加主分割器
|
||||
self.layouts["main_layout"].addWidget(self.splitters["main_splitter"])
|
||||
|
||||
# 将左右面板添加到主分割器
|
||||
self.splitters["main_splitter"].addWidget(self.controls["left_panel"])
|
||||
self.splitters["main_splitter"].addWidget(self.controls["right_panel"])
|
||||
|
||||
# 左侧面板布局
|
||||
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)
|
||||
|
||||
# DNA浏览器组布局
|
||||
self.layouts["dna_browser_layout"] = QtWidgets.QVBoxLayout(self.controls["dna_browser_group"])
|
||||
self.layouts["dna_browser_layout"].addWidget(self.controls["dna_list"])
|
||||
self.layouts["dna_browser_layout"].addWidget(self.buttons["refresh_dna"])
|
||||
|
||||
# 添加组到左侧面板布局
|
||||
self.layouts["left_layout"].addWidget(self.controls["dna_browser_group"])
|
||||
self.layouts["left_layout"].addStretch()
|
||||
|
||||
# 右侧面板布局
|
||||
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)
|
||||
|
||||
# DNA操作组布局
|
||||
self.layouts["dna_ops_layout"] = QtWidgets.QVBoxLayout(self.controls["dna_ops_group"])
|
||||
self.layouts["dna_ops_layout"].addWidget(self.buttons["import_skeleton"])
|
||||
self.layouts["dna_ops_layout"].addWidget(self.buttons["generate_body"])
|
||||
self.layouts["dna_ops_layout"].addWidget(self.buttons["calibrate_dna"])
|
||||
|
||||
# 骨骼操作组布局
|
||||
self.layouts["skeleton_ops_layout"] = QtWidgets.QVBoxLayout(self.controls["skeleton_ops_group"])
|
||||
self.layouts["skeleton_ops_layout"].addWidget(self.buttons["calibrate_skeleton"])
|
||||
self.layouts["skeleton_ops_layout"].addWidget(self.buttons["create_binding"])
|
||||
self.layouts["skeleton_ops_layout"].addWidget(self.buttons["copy_skin"])
|
||||
|
||||
# 添加组到右侧面板布局
|
||||
self.layouts["right_layout"].addWidget(self.controls["dna_ops_group"])
|
||||
self.layouts["right_layout"].addWidget(self.controls["skeleton_ops_group"])
|
||||
self.layouts["right_layout"].addStretch()
|
||||
|
||||
# 创建分割器大小处理器
|
||||
self.resize_handlers["main_splitter"] = ui_utils.SplitterResizeHandler(
|
||||
self.main_widget, self.splitters["main_splitter"], is_horizontal=True
|
||||
)
|
||||
|
||||
#========================================== CONNECTIONS ==========================================
|
||||
def connections():
|
||||
"""
|
||||
连接绑定系统UI信号和槽
|
||||
"""
|
||||
# 连接按钮点击事件到占位函数
|
||||
rig_buttons["load_dna"].clicked.connect(lambda: print("加载DNA功能待实现"))
|
||||
rig_buttons["import_joints"].clicked.connect(lambda: print("导入骨骼功能待实现"))
|
||||
rig_buttons["generate_body"].clicked.connect(lambda: print("生成身体功能待实现"))
|
||||
rig_buttons["calibrate_dna"].clicked.connect(lambda: print("DNA校准功能待实现"))
|
||||
rig_buttons["calibrate_joints"].clicked.connect(lambda: print("骨骼位置校准功能待实现"))
|
||||
rig_buttons["create_binding"].clicked.connect(lambda: print("创建绑定功能待实现"))
|
||||
rig_buttons["copy_skinning"].clicked.connect(lambda: print("复制蒙皮功能待实现"))
|
||||
rig_buttons["save_dna"].clicked.connect(lambda: print("保存DNA功能待实现"))
|
||||
|
||||
# 连接树形视图选择事件
|
||||
dna_browser_tree.itemSelectionChanged.connect(lambda: print("DNA文件选择已更改"))
|
||||
|
||||
# 连接关节列表选择事件
|
||||
joint_list.itemSelectionChanged.connect(lambda: print("骨骼选择已更改"))
|
||||
|
||||
#===================================== PLACEHOLDER FUNCTION ===================================
|
||||
def rigging_temp_function():
|
||||
return utils_rigging.rigging_temp_utils_function()
|
||||
#======================================= CONNECTION =====================================
|
||||
def create_connections(self):
|
||||
"""
|
||||
连接信号和槽
|
||||
设置UI控件的交互行为
|
||||
"""
|
||||
# DNA浏览器按钮连接
|
||||
self.buttons["refresh_dna"].clicked.connect(utils_rigging.rigging_temp_utils_function)
|
||||
|
||||
# DNA操作按钮连接
|
||||
self.buttons["import_skeleton"].clicked.connect(utils_rigging.rigging_temp_utils_function)
|
||||
self.buttons["generate_body"].clicked.connect(utils_rigging.rigging_temp_utils_function)
|
||||
self.buttons["calibrate_dna"].clicked.connect(utils_rigging.rigging_temp_utils_function)
|
||||
|
||||
# 骨骼操作按钮连接
|
||||
self.buttons["calibrate_skeleton"].clicked.connect(utils_rigging.rigging_temp_utils_function)
|
||||
self.buttons["create_binding"].clicked.connect(utils_rigging.rigging_temp_utils_function)
|
||||
self.buttons["copy_skin"].clicked.connect(utils_rigging.rigging_temp_utils_function)
|
@@ -1,119 +1,262 @@
|
||||
/* Plugin 统一样式表 */
|
||||
/* MetaFusion 插件样式表 */
|
||||
/* 作者: CGNICO */
|
||||
/* 版本: Alpha v1.0.0 */
|
||||
|
||||
/* 全局样式 */
|
||||
/* ==================== 全局样式 ==================== */
|
||||
QWidget {
|
||||
font-family: "Microsoft YaHei", "SimHei", sans-serif;
|
||||
font-size: 9pt;
|
||||
font-family: "Microsoft YaHei", "SimHei", "Arial", sans-serif;
|
||||
font-size: 12px;
|
||||
color: #E0E0E0;
|
||||
background-color: #333333;
|
||||
}
|
||||
|
||||
/* 菜单样式 */
|
||||
QMenuBar {
|
||||
background-color: #2D2D30;
|
||||
}
|
||||
|
||||
QLabel {
|
||||
color: #E0E0E0;
|
||||
}
|
||||
|
||||
QMenuBar::item {
|
||||
background-color: transparent;
|
||||
padding: 5px 10px;
|
||||
QLabel#mainTitleLabel {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #FFFFFF;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
QMenuBar::item:selected {
|
||||
background-color: #007ACC;
|
||||
color: white;
|
||||
}
|
||||
|
||||
QMenu {
|
||||
background-color: #1E1E1E;
|
||||
color: #E0E0E0;
|
||||
border: 1px solid #3F3F46;
|
||||
}
|
||||
|
||||
QMenu::item {
|
||||
padding: 5px 30px 5px 20px;
|
||||
}
|
||||
|
||||
QMenu::item:selected {
|
||||
background-color: #007ACC;
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* 工具栏样式 */
|
||||
QToolBar {
|
||||
background-color: #2D2D30;
|
||||
border: 1px solid #3F3F46;
|
||||
spacing: 3px;
|
||||
}
|
||||
|
||||
QToolBar::separator {
|
||||
background-color: #3F3F46;
|
||||
width: 1px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
/* 工具栏图标按钮样式 */
|
||||
QPushButton#ToolbarIconButton {
|
||||
background-color: #333333;
|
||||
border: none;
|
||||
padding: 1px;
|
||||
min-width: 24px;
|
||||
max-width: 24px;
|
||||
min-height: 24px;
|
||||
max-height: 24px;
|
||||
}
|
||||
|
||||
QPushButton#ToolbarIconButton:hover {
|
||||
background-color: #444444;
|
||||
}
|
||||
|
||||
QPushButton#ToolbarIconButton:pressed {
|
||||
background-color: #555555;
|
||||
}
|
||||
|
||||
/* 工具栏分隔符样式 */
|
||||
QFrame#ToolbarSeparator {
|
||||
background-color: #555555;
|
||||
max-width: 1px;
|
||||
min-width: 1px;
|
||||
}
|
||||
|
||||
/* 工具栏状态标签样式 */
|
||||
QLabel#StatusLabel {
|
||||
color: #CCCCCC;
|
||||
padding-right: 5px;
|
||||
font-size: 9pt;
|
||||
}
|
||||
|
||||
/* 标签页样式 */
|
||||
/* ==================== 标签页样式 ==================== */
|
||||
QTabWidget::pane {
|
||||
border: 1px solid #3F3F46;
|
||||
border: 1px solid #1E1E1E;
|
||||
background-color: #2D2D30;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
QTabBar::tab {
|
||||
background-color: #252526;
|
||||
color: #E0E0E0;
|
||||
border: 1px solid #3F3F46;
|
||||
border-bottom: none;
|
||||
padding: 5px 10px;
|
||||
background-color: #3E3E42;
|
||||
color: #CCCCCC;
|
||||
padding: 8px 15px;
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
min-width: 80px;
|
||||
border: 1px solid #1E1E1E;
|
||||
border-bottom: none;
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
QTabBar::tab:selected {
|
||||
background-color: #007ACC;
|
||||
color: white;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
QTabBar::tab:hover:!selected {
|
||||
background-color: #3E3E40;
|
||||
background-color: #505050;
|
||||
}
|
||||
|
||||
/* 分组框样式 */
|
||||
/* ==================== 按钮样式 ==================== */
|
||||
QPushButton {
|
||||
background-color: #3E3E42;
|
||||
color: #CCCCCC;
|
||||
border: 1px solid #1E1E1E;
|
||||
border-radius: 3px;
|
||||
padding: 5px 10px;
|
||||
min-height: 25px;
|
||||
}
|
||||
|
||||
QPushButton:hover {
|
||||
background-color: #505050;
|
||||
border: 1px solid #007ACC;
|
||||
}
|
||||
|
||||
QPushButton:pressed {
|
||||
background-color: #007ACC;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
QPushButton:disabled {
|
||||
background-color: #2D2D30;
|
||||
color: #656565;
|
||||
border: 1px solid #1E1E1E;
|
||||
}
|
||||
|
||||
/* 主要操作按钮 */
|
||||
QPushButton.primary {
|
||||
background-color: #007ACC;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
QPushButton.primary:hover {
|
||||
background-color: #1C97EA;
|
||||
}
|
||||
|
||||
QPushButton.primary:pressed {
|
||||
background-color: #0062A3;
|
||||
}
|
||||
|
||||
/* 危险操作按钮 */
|
||||
QPushButton.danger {
|
||||
background-color: #E51400;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
QPushButton.danger:hover {
|
||||
background-color: #FF2D1C;
|
||||
}
|
||||
|
||||
QPushButton.danger:pressed {
|
||||
background-color: #B30F00;
|
||||
}
|
||||
|
||||
/* ==================== 输入框样式 ==================== */
|
||||
QLineEdit, QTextEdit, QPlainTextEdit {
|
||||
background-color: #1E1E1E;
|
||||
color: #E0E0E0;
|
||||
border: 1px solid #3E3E42;
|
||||
border-radius: 3px;
|
||||
padding: 3px;
|
||||
selection-background-color: #264F78;
|
||||
}
|
||||
|
||||
QLineEdit:focus, QTextEdit:focus, QPlainTextEdit:focus {
|
||||
border: 1px solid #007ACC;
|
||||
}
|
||||
|
||||
QLineEdit:disabled, QTextEdit:disabled, QPlainTextEdit:disabled {
|
||||
background-color: #2D2D30;
|
||||
color: #656565;
|
||||
border: 1px solid #1E1E1E;
|
||||
}
|
||||
|
||||
/* ==================== 下拉框样式 ==================== */
|
||||
QComboBox {
|
||||
background-color: #1E1E1E;
|
||||
color: #E0E0E0;
|
||||
border: 1px solid #3E3E42;
|
||||
border-radius: 3px;
|
||||
padding: 3px 18px 3px 3px;
|
||||
min-height: 25px;
|
||||
}
|
||||
|
||||
QComboBox:hover {
|
||||
border: 1px solid #007ACC;
|
||||
}
|
||||
|
||||
QComboBox:on {
|
||||
background-color: #3E3E42;
|
||||
}
|
||||
|
||||
QComboBox::drop-down {
|
||||
subcontrol-origin: padding;
|
||||
subcontrol-position: top right;
|
||||
width: 15px;
|
||||
border-left: 1px solid #3E3E42;
|
||||
}
|
||||
|
||||
QComboBox::down-arrow {
|
||||
image: url(":/icons/dropdown_arrow.png");
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
QComboBox QAbstractItemView {
|
||||
background-color: #1E1E1E;
|
||||
color: #E0E0E0;
|
||||
border: 1px solid #3E3E42;
|
||||
selection-background-color: #007ACC;
|
||||
selection-color: #FFFFFF;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
/* ==================== 列表控件样式 ==================== */
|
||||
QListWidget, QTreeWidget, QTableWidget {
|
||||
background-color: #1E1E1E;
|
||||
color: #E0E0E0;
|
||||
border: 1px solid #3E3E42;
|
||||
border-radius: 3px;
|
||||
alternate-background-color: #2A2A2A;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
QListWidget::item, QTreeWidget::item, QTableWidget::item {
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
QListWidget::item:selected, QTreeWidget::item:selected, QTableWidget::item:selected {
|
||||
background-color: #007ACC;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
QListWidget::item:hover, QTreeWidget::item:hover, QTableWidget::item:hover {
|
||||
background-color: #3E3E42;
|
||||
}
|
||||
|
||||
/* ==================== 滚动条样式 ==================== */
|
||||
QScrollBar:vertical {
|
||||
background-color: #2D2D30;
|
||||
width: 12px;
|
||||
margin: 12px 0 12px 0;
|
||||
border: 1px solid #1E1E1E;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
QScrollBar::handle:vertical {
|
||||
background-color: #3E3E42;
|
||||
min-height: 20px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
QScrollBar::handle:vertical:hover {
|
||||
background-color: #505050;
|
||||
}
|
||||
|
||||
QScrollBar::add-line:vertical {
|
||||
border: none;
|
||||
background: none;
|
||||
height: 10px;
|
||||
subcontrol-position: bottom;
|
||||
subcontrol-origin: margin;
|
||||
}
|
||||
|
||||
QScrollBar::sub-line:vertical {
|
||||
border: none;
|
||||
background: none;
|
||||
height: 10px;
|
||||
subcontrol-position: top;
|
||||
subcontrol-origin: margin;
|
||||
}
|
||||
|
||||
QScrollBar:horizontal {
|
||||
background-color: #2D2D30;
|
||||
height: 12px;
|
||||
margin: 0 12px 0 12px;
|
||||
border: 1px solid #1E1E1E;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
QScrollBar::handle:horizontal {
|
||||
background-color: #3E3E42;
|
||||
min-width: 20px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
QScrollBar::handle:horizontal:hover {
|
||||
background-color: #505050;
|
||||
}
|
||||
|
||||
QScrollBar::add-line:horizontal {
|
||||
border: none;
|
||||
background: none;
|
||||
width: 10px;
|
||||
subcontrol-position: right;
|
||||
subcontrol-origin: margin;
|
||||
}
|
||||
|
||||
QScrollBar::sub-line:horizontal {
|
||||
border: none;
|
||||
background: none;
|
||||
width: 10px;
|
||||
subcontrol-position: left;
|
||||
subcontrol-origin: margin;
|
||||
}
|
||||
|
||||
/* ==================== 分组框样式 ==================== */
|
||||
QGroupBox {
|
||||
border: 1px solid #3F3F46;
|
||||
border: 1px solid #3E3E42;
|
||||
border-radius: 3px;
|
||||
margin-top: 10px;
|
||||
padding-top: 10px;
|
||||
@@ -124,232 +267,252 @@ QGroupBox::title {
|
||||
subcontrol-origin: margin;
|
||||
subcontrol-position: top left;
|
||||
padding: 0 5px;
|
||||
color: #E0E0E0;
|
||||
color: #007ACC;
|
||||
}
|
||||
|
||||
/* 下拉框样式 */
|
||||
QComboBox {
|
||||
background-color: #1E1E1E;
|
||||
color: #E0E0E0;
|
||||
border: 1px solid #3F3F46;
|
||||
border-radius: 3px;
|
||||
padding: 3px 18px 3px 3px;
|
||||
min-width: 6em;
|
||||
/* ==================== 分割器样式 ==================== */
|
||||
QSplitter::handle {
|
||||
background-color: #3E3E42;
|
||||
}
|
||||
|
||||
QComboBox::drop-down {
|
||||
subcontrol-origin: padding;
|
||||
subcontrol-position: top right;
|
||||
width: 15px;
|
||||
border-left: 1px solid #3F3F46;
|
||||
QSplitter::handle:horizontal {
|
||||
width: 2px;
|
||||
}
|
||||
|
||||
QComboBox QAbstractItemView {
|
||||
background-color: #1E1E1E;
|
||||
color: #E0E0E0;
|
||||
border: 1px solid #3F3F46;
|
||||
selection-background-color: #264F78;
|
||||
selection-color: white;
|
||||
QSplitter::handle:vertical {
|
||||
height: 2px;
|
||||
}
|
||||
|
||||
/* 按钮样式 */
|
||||
QPushButton {
|
||||
background-color: #0E639C;
|
||||
color: white;
|
||||
border: 1px solid #0E639C;
|
||||
border-radius: 3px;
|
||||
padding: 5px 10px;
|
||||
min-width: 80px;
|
||||
QSplitter::handle:hover {
|
||||
background-color: #007ACC;
|
||||
}
|
||||
|
||||
QPushButton:hover {
|
||||
background-color: #1177BB;
|
||||
border: 1px solid #1177BB;
|
||||
}
|
||||
|
||||
QPushButton:pressed {
|
||||
background-color: #00578A;
|
||||
border: 1px solid #00578A;
|
||||
}
|
||||
|
||||
QPushButton:disabled {
|
||||
background-color: #3F3F46;
|
||||
color: #9D9D9D;
|
||||
border: 1px solid #3F3F46;
|
||||
}
|
||||
|
||||
/* 输入框样式 */
|
||||
QLineEdit, QTextEdit, QPlainTextEdit {
|
||||
background-color: #1E1E1E;
|
||||
color: #E0E0E0;
|
||||
border: 1px solid #3F3F46;
|
||||
border-radius: 3px;
|
||||
padding: 3px;
|
||||
selection-background-color: #264F78;
|
||||
}
|
||||
|
||||
/* 单选框样式 */
|
||||
QRadioButton {
|
||||
color: #E0E0E0;
|
||||
spacing: 5px;
|
||||
}
|
||||
|
||||
QRadioButton::indicator {
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
}
|
||||
|
||||
/* 复选框样式 */
|
||||
QCheckBox {
|
||||
color: #E0E0E0;
|
||||
spacing: 5px;
|
||||
}
|
||||
|
||||
QCheckBox::indicator {
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
}
|
||||
|
||||
/* 滑块样式 */
|
||||
/* ==================== 滑块样式 ==================== */
|
||||
QSlider::groove:horizontal {
|
||||
border: 1px solid #3F3F46;
|
||||
height: 8px;
|
||||
background: #1E1E1E;
|
||||
margin: 2px 0;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #1E1E1E;
|
||||
height: 4px;
|
||||
background: #3E3E42;
|
||||
margin: 0 5px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
QSlider::handle:horizontal {
|
||||
background: #007ACC;
|
||||
border: 1px solid #007ACC;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
margin: -4px 0;
|
||||
border-radius: 7px;
|
||||
border: 1px solid #005F9E;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
margin: -5px 0;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
QSlider::handle:horizontal:hover {
|
||||
background: #1177BB;
|
||||
border: 1px solid #1177BB;
|
||||
background: #1C97EA;
|
||||
border: 1px solid #007ACC;
|
||||
}
|
||||
|
||||
/* 进度条样式 */
|
||||
QSlider::sub-page:horizontal {
|
||||
background: #007ACC;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
/* ==================== 复选框样式 ==================== */
|
||||
QCheckBox {
|
||||
spacing: 5px;
|
||||
}
|
||||
|
||||
QCheckBox::indicator {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
}
|
||||
|
||||
QCheckBox::indicator:unchecked {
|
||||
border: 1px solid #3E3E42;
|
||||
background-color: #1E1E1E;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
QCheckBox::indicator:unchecked:hover {
|
||||
border: 1px solid #007ACC;
|
||||
}
|
||||
|
||||
QCheckBox::indicator:checked {
|
||||
border: 1px solid #007ACC;
|
||||
background-color: #007ACC;
|
||||
border-radius: 2px;
|
||||
image: url(":/icons/checkmark.png");
|
||||
}
|
||||
|
||||
/* ==================== 单选框样式 ==================== */
|
||||
QRadioButton {
|
||||
spacing: 5px;
|
||||
}
|
||||
|
||||
QRadioButton::indicator {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
}
|
||||
|
||||
QRadioButton::indicator:unchecked {
|
||||
border: 1px solid #3E3E42;
|
||||
background-color: #1E1E1E;
|
||||
border-radius: 7px;
|
||||
}
|
||||
|
||||
QRadioButton::indicator:unchecked:hover {
|
||||
border: 1px solid #007ACC;
|
||||
}
|
||||
|
||||
QRadioButton::indicator:checked {
|
||||
border: 1px solid #007ACC;
|
||||
background-color: #1E1E1E;
|
||||
border-radius: 7px;
|
||||
}
|
||||
|
||||
QRadioButton::indicator:checked::before {
|
||||
content: "";
|
||||
display: block;
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
background-color: #007ACC;
|
||||
border-radius: 4px;
|
||||
margin: 3px;
|
||||
}
|
||||
|
||||
/* ==================== 进度条样式 ==================== */
|
||||
QProgressBar {
|
||||
border: 1px solid #3F3F46;
|
||||
border: 1px solid #3E3E42;
|
||||
border-radius: 3px;
|
||||
background-color: #1E1E1E;
|
||||
text-align: center;
|
||||
color: white;
|
||||
color: #E0E0E0;
|
||||
}
|
||||
|
||||
QProgressBar::chunk {
|
||||
background-color: #007ACC;
|
||||
width: 10px;
|
||||
margin: 0.5px;
|
||||
}
|
||||
|
||||
/* 列表和树视图样式 */
|
||||
QTreeView, QListView, QTableView {
|
||||
background-color: #1E1E1E;
|
||||
alternate-background-color: #262626;
|
||||
/* ==================== 菜单样式 ==================== */
|
||||
QMenuBar {
|
||||
background-color: #2D2D30;
|
||||
color: #E0E0E0;
|
||||
border: 1px solid #3F3F46;
|
||||
selection-background-color: #264F78;
|
||||
selection-color: white;
|
||||
outline: none;
|
||||
border-bottom: 1px solid #1E1E1E;
|
||||
}
|
||||
|
||||
QTreeView::item, QListView::item, QTableView::item {
|
||||
QMenuBar::item {
|
||||
background: transparent;
|
||||
padding: 5px 10px;
|
||||
}
|
||||
|
||||
QMenuBar::item:selected {
|
||||
background-color: #3E3E42;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
QMenuBar::item:pressed {
|
||||
background-color: #007ACC;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
QMenu {
|
||||
background-color: #1E1E1E;
|
||||
color: #E0E0E0;
|
||||
border: 1px solid #3E3E42;
|
||||
}
|
||||
|
||||
QMenu::item {
|
||||
padding: 5px 30px 5px 20px;
|
||||
}
|
||||
|
||||
QMenu::item:selected {
|
||||
background-color: #007ACC;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
QMenu::separator {
|
||||
height: 1px;
|
||||
background-color: #3E3E42;
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
/* ==================== 工具提示样式 ==================== */
|
||||
QToolTip {
|
||||
background-color: #1E1E1E;
|
||||
color: #E0E0E0;
|
||||
border: 1px solid #3E3E42;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
QTreeView::item:selected, QListView::item:selected, QTableView::item:selected {
|
||||
background-color: #264F78;
|
||||
color: white;
|
||||
}
|
||||
|
||||
QTreeView::item:hover, QListView::item:hover, QTableView::item:hover {
|
||||
background-color: #2A2D2E;
|
||||
}
|
||||
|
||||
QHeaderView::section {
|
||||
background-color: #252526;
|
||||
color: #E0E0E0;
|
||||
padding: 3px;
|
||||
border: 1px solid #3F3F46;
|
||||
}
|
||||
|
||||
/* 滚动条样式 */
|
||||
QScrollBar:vertical {
|
||||
background-color: #1E1E1E;
|
||||
width: 14px;
|
||||
margin: 14px 0 14px 0;
|
||||
border: 1px solid #3F3F46;
|
||||
}
|
||||
|
||||
QScrollBar::handle:vertical {
|
||||
background-color: #3E3E42;
|
||||
min-height: 20px;
|
||||
}
|
||||
|
||||
QScrollBar::add-line:vertical {
|
||||
border: 1px solid #3F3F46;
|
||||
background-color: #3E3E42;
|
||||
height: 14px;
|
||||
subcontrol-position: bottom;
|
||||
subcontrol-origin: margin;
|
||||
}
|
||||
|
||||
QScrollBar::sub-line:vertical {
|
||||
border: 1px solid #3F3F46;
|
||||
background-color: #3E3E42;
|
||||
height: 14px;
|
||||
subcontrol-position: top;
|
||||
subcontrol-origin: margin;
|
||||
}
|
||||
|
||||
QScrollBar:horizontal {
|
||||
background-color: #1E1E1E;
|
||||
height: 14px;
|
||||
margin: 0 14px 0 14px;
|
||||
border: 1px solid #3F3F46;
|
||||
}
|
||||
|
||||
QScrollBar::handle:horizontal {
|
||||
background-color: #3E3E42;
|
||||
min-width: 20px;
|
||||
}
|
||||
|
||||
QScrollBar::add-line:horizontal {
|
||||
border: 1px solid #3F3F46;
|
||||
background-color: #3E3E42;
|
||||
width: 14px;
|
||||
subcontrol-position: right;
|
||||
subcontrol-origin: margin;
|
||||
}
|
||||
|
||||
QScrollBar::sub-line:horizontal {
|
||||
border: 1px solid #3F3F46;
|
||||
background-color: #3E3E42;
|
||||
width: 14px;
|
||||
subcontrol-position: left;
|
||||
subcontrol-origin: margin;
|
||||
}
|
||||
|
||||
/* 状态栏样式 */
|
||||
/* ==================== 状态栏样式 ==================== */
|
||||
QStatusBar {
|
||||
background-color: #333333;
|
||||
background-color: #2D2D30;
|
||||
color: #E0E0E0;
|
||||
border-top: 1px solid #3F3F46;
|
||||
border-top: 1px solid #1E1E1E;
|
||||
}
|
||||
|
||||
QStatusBar::item {
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* 提示框样式 */
|
||||
QToolTip {
|
||||
background-color: #2D2D30;
|
||||
color: #E0E0E0;
|
||||
border: 1px solid #3F3F46;
|
||||
padding: 3px;
|
||||
/* ==================== 特定控件样式 ==================== */
|
||||
/* 标题标签 */
|
||||
QLabel[objectName="titleLabel"],
|
||||
QLabel[objectName="toolbarTitleLabel"],
|
||||
QLabel[objectName="definitionTitleLabel"],
|
||||
QLabel[objectName="geometryTitleLabel"],
|
||||
QLabel[objectName="riggingTitleLabel"],
|
||||
QLabel[objectName="behaviourTitleLabel"] {
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
color: #007ACC;
|
||||
padding: 5px;
|
||||
background-color: #252526;
|
||||
border-bottom: 1px solid #3E3E42;
|
||||
}
|
||||
|
||||
/* 底部滑块 */
|
||||
QSlider#bottomSlider {
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
/* 底部标签页按钮 */
|
||||
QPushButton[objectName*="tabButton"] {
|
||||
background-color: #3E3E42;
|
||||
color: #CCCCCC;
|
||||
border: 1px solid #1E1E1E;
|
||||
border-radius: 3px;
|
||||
padding: 5px;
|
||||
min-width: 40px;
|
||||
min-height: 25px;
|
||||
}
|
||||
|
||||
QPushButton[objectName*="tabButton"]:checked,
|
||||
QPushButton[objectName*="tabButton"]:pressed {
|
||||
background-color: #007ACC;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
QPushButton[objectName*="tabButton"]:hover:!checked {
|
||||
background-color: #505050;
|
||||
border: 1px solid #007ACC;
|
||||
}
|
||||
|
||||
/* 搜索框 */
|
||||
QLineEdit[objectName*="searchInput"],
|
||||
QLineEdit[objectName*="filterInput"] {
|
||||
background-color: #1E1E1E;
|
||||
color: #E0E0E0;
|
||||
border: 1px solid #3E3E42;
|
||||
border-radius: 3px;
|
||||
padding: 5px 25px 5px 5px;
|
||||
background-image: url(":/icons/search.png");
|
||||
background-repeat: no-repeat;
|
||||
background-position: right center;
|
||||
background-origin: content;
|
||||
}
|
||||
|
||||
QLineEdit[objectName*="searchInput"]:focus,
|
||||
QLineEdit[objectName*="filterInput"]:focus {
|
||||
border: 1px solid #007ACC;
|
||||
}
|
||||
|
@@ -12,185 +12,165 @@ Toolbar UI Module for Plugin
|
||||
- 创建RL4节点(用于切换DNA编辑的状态)
|
||||
- 删除RL4节点(用于切换DNA编辑的状态)
|
||||
"""
|
||||
|
||||
#===================================== IMPORT MODULES =====================================
|
||||
#========================================= 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
|
||||
|
||||
#===================================== IMPORT FUNCTIONS ===================================
|
||||
from scripts.utils import utils_toolbar as utils_toolbar
|
||||
from scripts.ui import ui_utils
|
||||
from scripts.utils import utils_toolbar
|
||||
#========================================== 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
|
||||
|
||||
#========================================== WIDGETS ==========================================
|
||||
# 全局变量存储UI控件
|
||||
toolbar_buttons = {}
|
||||
status_label = None
|
||||
|
||||
# 按钮图标和提示文本映射
|
||||
button_configs = {
|
||||
"open_file": {"icon": "open.png", "tooltip": "打开文件"},
|
||||
"save_file": {"icon": "save.png", "tooltip": "保存文件"},
|
||||
"save_as": {"icon": "save_new.png", "tooltip": "另存为"},
|
||||
"load_preset": {"icon": "import_preset.png", "tooltip": "加载预设"},
|
||||
"save_preset": {"icon": "export_preset.png", "tooltip": "导出预设"},
|
||||
"import_dna": {"icon": "import_dna.png", "tooltip": "导入DNA"},
|
||||
"export_dna": {"icon": "export_dna.png", "tooltip": "导出DNA"},
|
||||
"create_rl4": {"icon": "create_rl4_node.png", "tooltip": "创建RL4节点"},
|
||||
"delete_rl4": {"icon": "delete_rl4_node.png", "tooltip": "删除RL4节点"}
|
||||
}
|
||||
|
||||
def widgets():
|
||||
class ToolbarUI(ui_utils.BaseUI):
|
||||
"""
|
||||
创建工具栏UI控件
|
||||
工具栏UI类 - 负责显示工具栏界面和基础操作
|
||||
继承自BaseUI类,实现工具栏相关的UI功能
|
||||
"""
|
||||
global toolbar_buttons, status_label
|
||||
|
||||
# 创建按钮的辅助函数
|
||||
def create_icon_button(button_id, size=24):
|
||||
config = button_configs[button_id]
|
||||
button = QtWidgets.QPushButton()
|
||||
button.setToolTip(config["tooltip"]) # 设置提示文本
|
||||
button.setFixedSize(size, size) # 设置固定大小
|
||||
# 设置样式类名
|
||||
button.setObjectName("ToolbarIconButton")
|
||||
#========================================== INIT ========================================
|
||||
def __init__(self):
|
||||
"""
|
||||
初始化工具栏UI
|
||||
创建主控件和布局,并连接信号和槽
|
||||
"""
|
||||
super(ToolbarUI, self).__init__()
|
||||
|
||||
# 设置图标
|
||||
icon_path = os.path.abspath(os.path.join(ICONS_PATH, config["icon"]))
|
||||
if os.path.exists(icon_path):
|
||||
icon = QtGui.QIcon(icon_path)
|
||||
if not icon.isNull():
|
||||
button.setIcon(icon)
|
||||
button.setIconSize(QtCore.QSize(size-4, size-4)) # 图标尺寸稍小于按钮
|
||||
print(f"成功设置按钮图标 {button_id}: {icon_path}")
|
||||
else:
|
||||
print(f"图标加载失败 {button_id}: {icon_path}")
|
||||
else:
|
||||
print(f"警告: 图标文件未找到 {button_id}: {icon_path}")
|
||||
|
||||
return button
|
||||
|
||||
# 创建所有按钮
|
||||
# 文件操作按钮
|
||||
toolbar_buttons["open_file"] = create_icon_button("open_file")
|
||||
toolbar_buttons["save_file"] = create_icon_button("save_file")
|
||||
toolbar_buttons["save_as"] = create_icon_button("save_as")
|
||||
|
||||
# 预设操作按钮
|
||||
toolbar_buttons["load_preset"] = create_icon_button("load_preset")
|
||||
toolbar_buttons["save_preset"] = create_icon_button("save_preset")
|
||||
|
||||
# DNA操作按钮
|
||||
toolbar_buttons["import_dna"] = create_icon_button("import_dna")
|
||||
toolbar_buttons["export_dna"] = create_icon_button("export_dna")
|
||||
|
||||
# RL4节点操作按钮
|
||||
toolbar_buttons["create_rl4"] = create_icon_button("create_rl4")
|
||||
toolbar_buttons["delete_rl4"] = create_icon_button("delete_rl4")
|
||||
|
||||
# 移除DNA下拉菜单
|
||||
|
||||
# 状态标签
|
||||
status_label = QtWidgets.QLabel("就绪")
|
||||
status_label.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
||||
status_label.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
status_label.setObjectName("StatusLabel")
|
||||
# status_label.setStyleSheet("""
|
||||
# QLabel {
|
||||
# color: #CCCCCC;
|
||||
# padding-right: 5px;
|
||||
# font-size: 9pt;
|
||||
# }
|
||||
# """)
|
||||
# 创建主控件
|
||||
self.main_widget = QtWidgets.QWidget()
|
||||
self.main_widget.setObjectName("toolbarMainWidget")
|
||||
|
||||
# 初始化UI
|
||||
self.create_widgets()
|
||||
self.create_layouts()
|
||||
self.create_connections()
|
||||
|
||||
#========================================== LAYOUTS ==========================================
|
||||
def layouts(parent_frame=None):
|
||||
"""
|
||||
创建工具栏UI布局
|
||||
|
||||
Args:
|
||||
parent_frame: 父容器控件,由Main.py传入
|
||||
"""
|
||||
# 获取父容器(在Main.py中创建的toolbar_frame)
|
||||
if not parent_frame:
|
||||
parent_frame = ui_utils.get_parent_widget("toolbar_frame")
|
||||
if not parent_frame:
|
||||
print("无法获取父容器,布局创建失败")
|
||||
return
|
||||
|
||||
# 创建主布局
|
||||
main_layout = parent_frame.layout()
|
||||
if not main_layout:
|
||||
print("父容器没有布局,布局创建失败")
|
||||
return
|
||||
|
||||
# 创建工具栏布局
|
||||
toolbar_layout = QtWidgets.QHBoxLayout()
|
||||
toolbar_layout.setContentsMargins(2, 2, 2, 2)
|
||||
toolbar_layout.setSpacing(2) # 减小按钮之间的间距
|
||||
toolbar_layout.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint) # 设置布局约束为默认,允许自适应
|
||||
|
||||
# 创建分隔符样式
|
||||
def create_separator():
|
||||
separator = QtWidgets.QFrame()
|
||||
separator.setFrameShape(QtWidgets.QFrame.VLine)
|
||||
separator.setFrameShadow(QtWidgets.QFrame.Sunken)
|
||||
separator.setObjectName("ToolbarSeparator")
|
||||
return separator
|
||||
|
||||
# 添加文件操作按钮
|
||||
toolbar_layout.addWidget(toolbar_buttons["open_file"])
|
||||
toolbar_layout.addWidget(toolbar_buttons["save_file"])
|
||||
toolbar_layout.addWidget(toolbar_buttons["save_as"])
|
||||
toolbar_layout.addWidget(create_separator()) # 使用自定义分隔符
|
||||
|
||||
# 添加预设操作按钮
|
||||
toolbar_layout.addWidget(toolbar_buttons["load_preset"])
|
||||
toolbar_layout.addWidget(toolbar_buttons["save_preset"])
|
||||
toolbar_layout.addWidget(create_separator()) # 使用自定义分隔符
|
||||
|
||||
# 添加DNA操作按钮
|
||||
toolbar_layout.addWidget(toolbar_buttons["import_dna"])
|
||||
toolbar_layout.addWidget(toolbar_buttons["export_dna"])
|
||||
toolbar_layout.addWidget(create_separator()) # 使用自定义分隔符
|
||||
|
||||
# 添加RL4节点操作按钮
|
||||
toolbar_layout.addWidget(toolbar_buttons["create_rl4"])
|
||||
toolbar_layout.addWidget(toolbar_buttons["delete_rl4"])
|
||||
toolbar_layout.addStretch()
|
||||
toolbar_layout.addWidget(status_label)
|
||||
|
||||
# 添加到主布局
|
||||
main_layout.addLayout(toolbar_layout)
|
||||
#========================================= WIDGET =======================================
|
||||
def create_widgets(self):
|
||||
"""
|
||||
创建工具栏UI控件
|
||||
包括按钮、标签、输入框等
|
||||
"""
|
||||
# 标题标签
|
||||
self.controls["title_label"] = QtWidgets.QLabel(LANG.get("toolbar_title", "工具栏"))
|
||||
self.controls["title_label"].setObjectName("toolbarTitleLabel")
|
||||
self.controls["title_label"].setAlignment(QtCore.Qt.AlignCenter)
|
||||
|
||||
# 预设组
|
||||
self.controls["preset_group"] = QtWidgets.QGroupBox(LANG.get("preset_group", "预设"))
|
||||
self.controls["preset_group"].setObjectName("presetGroup")
|
||||
|
||||
# 预设标签和下拉框
|
||||
self.controls["preset_label"] = QtWidgets.QLabel(LANG.get("preset", "预设:"))
|
||||
self.controls["preset_combo"] = QtWidgets.QComboBox()
|
||||
self.controls["preset_combo"].setObjectName("presetCombo")
|
||||
|
||||
# 预设按钮
|
||||
self.buttons["load_preset"] = QtWidgets.QPushButton(LANG.get("load_preset", "加载预设"))
|
||||
self.buttons["save_preset"] = QtWidgets.QPushButton(LANG.get("save_preset", "保存预设"))
|
||||
|
||||
# DNA操作组
|
||||
self.controls["dna_group"] = QtWidgets.QGroupBox(LANG.get("dna_operations", "DNA操作"))
|
||||
self.controls["dna_group"].setObjectName("dnaGroup")
|
||||
|
||||
# DNA操作按钮
|
||||
self.buttons["import_dna"] = QtWidgets.QPushButton(LANG.get("import_dna", "导入DNA"))
|
||||
self.buttons["export_dna"] = QtWidgets.QPushButton(LANG.get("export_dna", "导出DNA"))
|
||||
self.buttons["create_rl4"] = QtWidgets.QPushButton(LANG.get("create_rl4", "创建RL4节点"))
|
||||
self.buttons["delete_rl4"] = QtWidgets.QPushButton(LANG.get("delete_rl4", "删除RL4节点"))
|
||||
|
||||
#========================================== CONNECTIONS ==========================================
|
||||
def connections():
|
||||
"""
|
||||
连接工具栏UI信号和槽
|
||||
"""
|
||||
# 文件操作按钮连接
|
||||
toolbar_buttons["open_file"].clicked.connect(lambda: print("打开文件功能待实现"))
|
||||
toolbar_buttons["save_file"].clicked.connect(lambda: print("保存文件功能待实现"))
|
||||
toolbar_buttons["save_as"].clicked.connect(lambda: print("另存为功能待实现"))
|
||||
|
||||
# 预设操作按钮连接
|
||||
toolbar_buttons["load_preset"].clicked.connect(lambda: print("加载预设功能待实现"))
|
||||
toolbar_buttons["save_preset"].clicked.connect(lambda: print("导出预设功能待实现"))
|
||||
|
||||
# DNA操作按钮连接
|
||||
toolbar_buttons["import_dna"].clicked.connect(lambda: print("导入DNA功能待实现"))
|
||||
toolbar_buttons["export_dna"].clicked.connect(lambda: print("导出DNA功能待实现"))
|
||||
|
||||
# RL4节点操作按钮连接
|
||||
toolbar_buttons["create_rl4"].clicked.connect(lambda: print("创建RL4节点功能待实现"))
|
||||
toolbar_buttons["delete_rl4"].clicked.connect(lambda: print("删除RL4节点功能待实现"))
|
||||
#========================================= LAYOUT =======================================
|
||||
def create_layouts(self):
|
||||
"""
|
||||
创建工具栏UI布局
|
||||
组织控件的排列和层次结构
|
||||
"""
|
||||
# 主布局
|
||||
self.layouts["main_layout"] = QtWidgets.QVBoxLayout(self.main_widget)
|
||||
self.layouts["main_layout"].setContentsMargins(5, 5, 5, 5)
|
||||
self.layouts["main_layout"].setSpacing(5)
|
||||
|
||||
# 添加标题标签
|
||||
self.layouts["main_layout"].addWidget(self.controls["title_label"])
|
||||
|
||||
# 预设组布局
|
||||
self.layouts["preset_layout"] = QtWidgets.QVBoxLayout(self.controls["preset_group"])
|
||||
|
||||
# 预设选择布局
|
||||
self.layouts["preset_select_layout"] = QtWidgets.QHBoxLayout()
|
||||
self.layouts["preset_select_layout"].addWidget(self.controls["preset_label"])
|
||||
self.layouts["preset_select_layout"].addWidget(self.controls["preset_combo"])
|
||||
|
||||
# 预设按钮布局
|
||||
self.layouts["preset_buttons_layout"] = QtWidgets.QHBoxLayout()
|
||||
self.layouts["preset_buttons_layout"].addWidget(self.buttons["load_preset"])
|
||||
self.layouts["preset_buttons_layout"].addWidget(self.buttons["save_preset"])
|
||||
|
||||
# 添加到预设组布局
|
||||
self.layouts["preset_layout"].addLayout(self.layouts["preset_select_layout"])
|
||||
self.layouts["preset_layout"].addLayout(self.layouts["preset_buttons_layout"])
|
||||
|
||||
# DNA操作组布局
|
||||
self.layouts["dna_layout"] = QtWidgets.QVBoxLayout(self.controls["dna_group"])
|
||||
|
||||
# DNA操作按钮布局
|
||||
self.layouts["dna_buttons_layout"] = QtWidgets.QGridLayout()
|
||||
self.layouts["dna_buttons_layout"].addWidget(self.buttons["import_dna"], 0, 0)
|
||||
self.layouts["dna_buttons_layout"].addWidget(self.buttons["export_dna"], 0, 1)
|
||||
self.layouts["dna_buttons_layout"].addWidget(self.buttons["create_rl4"], 1, 0)
|
||||
self.layouts["dna_buttons_layout"].addWidget(self.buttons["delete_rl4"], 1, 1)
|
||||
|
||||
# 添加到DNA操作组布局
|
||||
self.layouts["dna_layout"].addLayout(self.layouts["dna_buttons_layout"])
|
||||
|
||||
# 添加组到主布局
|
||||
self.layouts["main_layout"].addWidget(self.controls["preset_group"])
|
||||
self.layouts["main_layout"].addWidget(self.controls["dna_group"])
|
||||
self.layouts["main_layout"].addStretch()
|
||||
|
||||
#===================================== PLACEHOLDER FUNCTION ===================================
|
||||
def toolbar_temp_function():
|
||||
return utils_toolbar.toolbar_temp_utils_function()
|
||||
#======================================= CONNECTION =====================================
|
||||
def create_connections(self):
|
||||
"""
|
||||
连接信号和槽
|
||||
设置UI控件的交互行为
|
||||
"""
|
||||
# 预设按钮连接
|
||||
self.buttons["load_preset"].clicked.connect(utils_toolbar.toolbar_temp_utils_function)
|
||||
self.buttons["save_preset"].clicked.connect(utils_toolbar.toolbar_temp_utils_function)
|
||||
|
||||
# DNA操作按钮连接
|
||||
self.buttons["import_dna"].clicked.connect(utils_toolbar.toolbar_temp_utils_function)
|
||||
self.buttons["export_dna"].clicked.connect(utils_toolbar.toolbar_temp_utils_function)
|
||||
self.buttons["create_rl4"].clicked.connect(utils_toolbar.toolbar_temp_utils_function)
|
||||
self.buttons["delete_rl4"].clicked.connect(utils_toolbar.toolbar_temp_utils_function)
|
||||
|
@@ -5,17 +5,108 @@
|
||||
UI Utilities Module for Plugin
|
||||
UI工具模块 - 提供UI相关的通用函数
|
||||
"""
|
||||
|
||||
#===================================== IMPORT MODULES =====================================
|
||||
#========================================= 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
|
||||
#========================================== CONFIG ========================================
|
||||
import config
|
||||
#===================================== UI UTILITY FUNCTIONS ===================================
|
||||
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
|
||||
|
||||
TOOL_NAME = config.TOOL_NAME
|
||||
#============================================ INIT ==========================================
|
||||
# 定义窗口大小变化事件处理类
|
||||
# 用于监听窗口大小变化并调整分割器宽度
|
||||
class SplitterResizeHandler(QtCore.QObject):
|
||||
def __init__(self, parent_tab, main_splitter, is_horizontal=True):
|
||||
super(SplitterResizeHandler, self).__init__(parent_tab)
|
||||
self.parent_tab = parent_tab
|
||||
self.main_splitter = main_splitter
|
||||
self.is_horizontal = is_horizontal # 是否为水平分割器
|
||||
|
||||
# 安装事件过滤器到父标签页
|
||||
self.parent_tab.installEventFilter(self)
|
||||
|
||||
def eventFilter(self, obj, event):
|
||||
# 监听大小变化事件
|
||||
if obj == self.parent_tab and event.type() == QtCore.QEvent.Resize:
|
||||
# 当窗口大小变化时,调整分割器宽度
|
||||
self.adjustSplitterSizes()
|
||||
return super(SplitterResizeHandler, self).eventFilter(obj, event)
|
||||
|
||||
def adjustSplitterSizes(self):
|
||||
# 确保分割器存在且父标签页可见
|
||||
if self.main_splitter and self.parent_tab.isVisible():
|
||||
if self.is_horizontal:
|
||||
# 获取父标签页当前宽度
|
||||
width = self.parent_tab.width()
|
||||
# 设置分割器左右宽度均等
|
||||
self.main_splitter.setSizes([width // 2, width // 2])
|
||||
print(f"分割器 - 窗口大小变化,调整水平分割器宽度为: {width // 2}, {width // 2}")
|
||||
else:
|
||||
# 获取父标签页当前高度
|
||||
height = self.parent_tab.height()
|
||||
# 设置分割器上下比例为3:1
|
||||
self.main_splitter.setSizes([height * 3 // 4, height // 4])
|
||||
print(f"分割器 - 窗口大小变化,调整垂直分割器高度为: {height * 3 // 4}, {height // 4}")
|
||||
|
||||
# 使用类来管理UI控件,避免全局变量
|
||||
class BaseUI:
|
||||
"""
|
||||
基础UI类 - 管理所有UI控件
|
||||
使用字典存储控件、按钮、布局和分割器引用,避免全局变量
|
||||
"""
|
||||
def __init__(self):
|
||||
# UI控件字典
|
||||
self.controls = {}
|
||||
# 按钮字典
|
||||
self.buttons = {}
|
||||
# 布局字典
|
||||
self.layouts = {}
|
||||
# 分割器字典
|
||||
self.splitters = {}
|
||||
# 分割器大小处理器字典
|
||||
self.resize_handlers = {}
|
||||
|
||||
def get_maya_main_window():
|
||||
"""
|
||||
获取Maya主窗口
|
||||
|
||||
Returns:
|
||||
QWidget: Maya主窗口控件
|
||||
"""
|
||||
main_window_ptr = omui.MQtUtil.mainWindow()
|
||||
return wrapInstance(int(main_window_ptr), QtWidgets.QWidget)
|
||||
|
||||
def get_parent_widget(widget_name):
|
||||
"""
|
||||
@@ -49,14 +140,4 @@ def get_parent_widget(widget_name):
|
||||
return child
|
||||
|
||||
print(f"无法找到控件: {widget_name}")
|
||||
return None
|
||||
|
||||
def get_maya_main_window():
|
||||
"""
|
||||
获取Maya主窗口
|
||||
|
||||
Returns:
|
||||
QWidget: Maya主窗口控件
|
||||
"""
|
||||
main_window_ptr = omui.MQtUtil.mainWindow()
|
||||
return wrapInstance(int(main_window_ptr), QtWidgets.QWidget)
|
||||
return None
|
@@ -3,11 +3,13 @@
|
||||
|
||||
"""
|
||||
Behaviour function module
|
||||
行为系统工具函数模块 - 提供行为系统UI所需的所有功能函数
|
||||
"""
|
||||
|
||||
#===================================== IMPORT MODULES =====================================
|
||||
import maya.cmds as cmds
|
||||
import pymel.core as pm
|
||||
from Qt import QtWidgets, QtCore, QtGui
|
||||
import importlib
|
||||
import sys
|
||||
import os
|
||||
@@ -19,5 +21,4 @@ def behaviour_temp_utils_function():
|
||||
Placeholder function for behaviour module
|
||||
This function will be replaced with actual functionality in future updates
|
||||
"""
|
||||
print("Behaviour module initialized with placeholder function")
|
||||
return True
|
||||
print("Behaviour module temporary function called")
|
@@ -3,6 +3,7 @@
|
||||
|
||||
"""
|
||||
Definition function module
|
||||
定义统工具函数模块 - 提供定义统UI所需的所有功能函数
|
||||
"""
|
||||
|
||||
#===================================== IMPORT MODULES =====================================
|
||||
@@ -19,5 +20,4 @@ def definition_temp_utils_function():
|
||||
Placeholder function for definition module
|
||||
This function will be replaced with actual functionality in future updates
|
||||
"""
|
||||
print("Definition module initialized with placeholder function")
|
||||
return True
|
||||
print("Definition module temporary function called")
|
Reference in New Issue
Block a user