284 lines
12 KiB
Python
284 lines
12 KiB
Python
#!/usr/bin/env python
|
||
# -*- coding: utf-8 -*-
|
||
|
||
"""
|
||
Main module for Metahuman customize plugin
|
||
主模块 - 负责初始化UI和功能集成
|
||
功能: 从ui模块加载子模块显示
|
||
作者: Virtuos Games
|
||
版本: Alpha v1.0.0
|
||
"""
|
||
#===================================== IMPORT MODULES =====================================
|
||
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 UI MODULES ===================================
|
||
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 ==================================
|
||
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 ===================================
|
||
class MainWindow(QtWidgets.QWidget):
|
||
def __init__(self, parent=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.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
|
||
self.setMinimumSize(300, 600) # 减小最小高度,让窗口更灵活
|
||
|
||
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)
|
||
|
||
# 加载样式表
|
||
if os.path.exists(STYLE_FILE):
|
||
try:
|
||
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}")
|
||
else:
|
||
print(f"警告: 样式表文件不存在: {STYLE_FILE}")
|
||
|
||
def create_connections(self):
|
||
# 连接各模块的信号和槽
|
||
toolbar.connections()
|
||
geometry.connections()
|
||
rigging.connections()
|
||
behaviour.connections()
|
||
definition.connections()
|
||
|
||
# 标签页切换信号
|
||
self.main_tab.currentChanged.connect(self.on_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 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()
|
||
|
||
# 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
|
||
except Exception as e:
|
||
error_msg = f"Error initializing {TOOL_NAME} plugin: {str(e)}"
|
||
print(error_msg)
|
||
traceback.print_exc()
|
||
cmds.warning(error_msg)
|
||
return None
|
||
|
||
|
||
# Auto-run when imported
|
||
if __name__ == "__main__":
|
||
main()
|