From 171ef9e851516cfe515339a73903358f9cbf68e6 Mon Sep 17 00:00:00 2001 From: Jeffreytsai1004 Date: Tue, 7 Jan 2025 02:18:44 +0800 Subject: [PATCH] Update metafusion.py --- metafusion.py | 305 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 304 insertions(+), 1 deletion(-) diff --git a/metafusion.py b/metafusion.py index 5f28270..366082b 100644 --- a/metafusion.py +++ b/metafusion.py @@ -1 +1,304 @@ - \ No newline at end of file +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from PySide2 import QtWidgets, QtCore, QtGui +from shiboken2 import wrapInstance +from maya import OpenMayaUI as omui +import maya.cmds as cmds +import maya.mel as mel +import maya.utils as utils +import importlib +import traceback +import subprocess +import webbrowser +import locale +import sys +import os + +# 全局变量声明 +TOOL_PATH = os.path.dirname(os.path.abspath(__file__)).replace('\\', '/') +TOOL_ICON = os.path.join(TOOL_PATH, "icons", "logo.png") +if not os.path.exists(TOOL_ICON): + print(f"Warning: Icon file not found at {TOOL_ICON}") + TOOL_ICON = "" # 设置为空字符串而不是 None +MAYA_VERSION = cmds.about(version=True) +TOOL_NAME = "MetaFusion" +TOOL_VERSION = "v1.0.0" +TOOL_AUTHOR = "CGNICO" +CURRENT_LANG = "en_US" +WKSP_CTRL = TOOL_NAME +DNA_PATH = "" +WKSP_PATH = "MetaFusion" +HelpURL = f"https://gitea.cgnico.com/CGNICO/{TOOL_NAME}/wiki" + +#==================================================== GLOBAL FUNCTIONS ==================================================== +class SetButton(QtWidgets.QPushButton): + """ + Custom rounded button class + + Features: + - Rounded design + - Custom color and hover effect + - Bold text + """ + def __init__(self, text="", icon=None, color="#D0D0D0", hover_color="#E0E0E0", pressed_color="#C0C0C0"): + super(SetButton, self).__init__(text) + if icon: + self.setIcon(icon) + self.setIconSize(QtCore.QSize(24, 24)) + self.setMinimumHeight(30) # Set minimum height + self.setStyleSheet( + f""" + QPushButton {{ + background-color: {color}; + color: #303030; + border-radius: 10px; + padding: 5px; + font-weight: bold; + text-align: center; + }} + QPushButton:hover {{ + background-color: {hover_color}; + }} + QPushButton:pressed {{ + background-color: {pressed_color}; + }} + """ + ) + +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) + +LANG = { + 'en_US': { + "Group 01": "Group 01", + "Group 02": "Group 02", + "Button 01": "Button 01", + "Button 02": "Button 02", + "DOCUMENT": "DOCUMENT", + "Help": "Help", + "Switch Language": "Switch Language" + }, + 'zh_CN': { + "Group 01": "组 01", + "Group 02": "组 02", + "Button 01": "按钮 01", + "Button 02": "按钮 02", + "DOCUMENT": "文档", + "Help": "帮助", + "Switch Language": "切换语言" + } +} + +#==================================================== MAIN WINDOW CLASS ==================================================== +class MainWindow(QtWidgets.QWidget): + def __init__(self, parent=None): + super(MainWindow, self).__init__(parent) + self.setWindowTitle(TOOL_NAME) + self.setObjectName(TOOL_NAME) + self.setWindowFlags(QtCore.Qt.Window) + self.setAttribute(QtCore.Qt.WA_DeleteOnClose) + self.setSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Preferred) + self.setMinimumSize(300, 800) + self.create_widgets() + self.create_layouts() + self.create_connections() + + if os.path.exists(TOOL_ICON): + self.setWindowIcon(QtGui.QIcon(TOOL_ICON)) + else: + print(f"WARNING: Icon file not found: {TOOL_ICON}") + +#==================================================== UI COMPONENTS ==================================================== + def create_widgets(self): + + self.group_01 = QtWidgets.QGroupBox(LANG[CURRENT_LANG]["Group 01"]) + self.group_01_button = SetButton(LANG[CURRENT_LANG]["Button 01"], color="#A7C6ED", hover_color="#B2D3F0", pressed_color="#8BB8E0") + self.group_02 = QtWidgets.QGroupBox(LANG[CURRENT_LANG]["Group 02"]) + self.group_02_button = SetButton(LANG[CURRENT_LANG]["Button 02"], color="#FFCCBC", hover_color="#FFAB91", pressed_color="#FF8A65") + + self.help_btn = QtWidgets.QPushButton(LANG[CURRENT_LANG]["DOCUMENT"]) + self.help_btn.setToolTip(LANG[CURRENT_LANG]["Help"]) + self.help_btn.setFixedSize(100, 20) + self.help_btn.setStyleSheet(""" + QPushButton { + background-color: transparent; + border: none; + color: gray; + font-weight: bold; + } + QPushButton:hover { + color: black; + } + """) + self.lang_btn = QtWidgets.QPushButton("EN" if CURRENT_LANG == 'zh_CN' else "ZH") + self.lang_btn.setToolTip(LANG[CURRENT_LANG]["Switch Language"]) + self.lang_btn.setFixedSize(30, 20) + self.lang_btn.setStyleSheet(""" + QPushButton { + background-color: transparent; + border: none; + color: gray; + font-weight: bold; + } + QPushButton:hover { + color: black; + } + """) + + def create_layouts(self): + main_layout = QtWidgets.QVBoxLayout(self) + main_layout.setContentsMargins(2, 2, 2, 2) + main_layout.addStretch() + main_layout.addWidget(self.group_01) + main_layout.addWidget(self.group_01_button) + main_layout.addWidget(self.group_02) + main_layout.addWidget(self.group_02_button) + main_layout.addStretch() + + # Bottom layout + bottom_layout = QtWidgets.QHBoxLayout() + icon_label = QtWidgets.QLabel() + if TOOL_ICON and os.path.exists(TOOL_ICON): + icon = QtGui.QPixmap(TOOL_ICON).scaled(24, 24, QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation) + icon_label.setPixmap(icon) + + bottom_layout.addWidget(icon_label) + version_label = QtWidgets.QLabel(f"{TOOL_VERSION}") + version_label.setStyleSheet("color: gray; font-size: 12px;") + bottom_layout.addWidget(version_label) + bottom_layout.addStretch() + bottom_layout.addWidget(self.help_btn) + bottom_layout.addWidget(self.lang_btn) + main_layout.addLayout(bottom_layout) + + def create_connections(self): + self.group_01_button.clicked.connect(self.run_group_01) + self.group_02_button.clicked.connect(self.run_group_02) + self.help_btn.clicked.connect(self.show_help) + self.lang_btn.clicked.connect(self.switch_language) + + def run_group_01(self): + print("Button 01") + + def run_group_02(self): + print("Button 02") + + def dock_to_maya(self): + if not WKSP_CTRL: + print("Error: WKSP_CTRL is not defined") + return + + if cmds.workspaceControl(WKSP_CTRL, exists=True): + cmds.deleteUI(WKSP_CTRL) + + def create_control(): + try: + if not self.objectName(): + self.setObjectName(TOOL_NAME) + + workspace_control = cmds.workspaceControl( + WKSP_CTRL, + label=TOOL_NAME, + floating=True, + retain=False, + resizeWidth=True, + initialWidth=300, + minimumWidth=300 + ) + + if not workspace_control: + raise RuntimeError("Failed to create workspace control") + + cmds.workspaceControl(WKSP_CTRL, e=True, resizeWidth=True) + + try: + cmds.control(self.objectName(), e=True, p=workspace_control) + except Exception as e: + print(f"Error parenting control: {e}") + return + + except Exception as e: + print(f"Error creating workspace control: {e}") + traceback.print_exc() + + cmds.evalDeferred(create_control) + + def show_help(self): + # Specify the URL of the website you want to open + webbrowser.open(HelpURL) + + def switch_language(self): + global CURRENT_LANG + CURRENT_LANG = 'en_US' if CURRENT_LANG == 'zh_CN' else 'zh_CN' + self.lang_btn.setText("EN" if CURRENT_LANG == 'zh_CN' else "CN") + self.retranslate_ui() + + QtWidgets.QToolTip.showText( + self.lang_btn.mapToGlobal(QtCore.QPoint(0, -30)), + "Language switched" if CURRENT_LANG == 'en_US' else "语言已切换", + self.lang_btn + ) + +def show(): + global main_window + + try: + current_width = 300 + if cmds.workspaceControl(WKSP_CTRL, exists=True): + try: + current_width = cmds.workspaceControl(WKSP_CTRL, q=True, width=True) + except: + pass + cmds.deleteUI(WKSP_CTRL, control=True) + + if 'main_window' in globals() and main_window: + try: + main_window.close() + main_window.deleteLater() + except: + pass + except Exception as e: + print(f"Error cleaning up previous window: {e}") + + def create_ui(retry_count=0, width=300): + global main_window + try: + if not WKSP_CTRL: + raise ValueError("WKSP_CTRL is not defined") + + main_window = MainWindow() + if not main_window: + raise RuntimeError("Failed to create main window") + + # 使用 try-except 包装每个 evalDeferred 调用 + def deferred_actions(): + try: + main_window.dock_to_maya() + cmds.workspaceControl(WKSP_CTRL, e=True, width=width) + cmds.workspaceControl(WKSP_CTRL, e=True, resizeWidth=True) + except Exception as e: + print(f"Error in deferred actions: {e}") + + cmds.evalDeferred(deferred_actions) + + except Exception as e: + if retry_count < 3: + print(f"{TOOL_NAME} creation failed, retrying... (Attempt {retry_count + 1})") + print(f"Error: {str(e)}") + utils.executeDeferred(lambda: create_ui(retry_count + 1, width)) + else: + print(f"Failed to create {TOOL_NAME} after 3 attempts:") + traceback.print_exc() + + utils.executeDeferred(lambda: create_ui(width=current_width)) + +if __name__ == "__main__": + show()