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()
|
||||
|
Reference in New Issue
Block a user