MetaBox/Scripts/MetaBox.py
2025-01-14 01:57:26 +08:00

1645 lines
85 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#===================================== IMPORT MODULES =====================================
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 webbrowser
import locale
import sys
import os, subprocess
#===================================== IMPORT FUNCTIONS ===================================
from Modeling.Manage import Rename
from Modeling.Edit import (
SpeedCut,
EvenEdgeLoop,
SpeedBend,
PolyFold,
ArcDeformer,
InstantDrag,
UnBevel,
RoundInset,
CreasePlus,
EdgeSensei,
AlignEdge,
AutoSnap,
XgenController,
)
from Modeling.Edit import gs_curvetools
from Modeling.Select import (
EdgeLoopSmartSelect,
SamePositionSelector,
IntervalSelectEdge,
)
from Modeling.UV import UVSetEditor
from Metahuman.Custom import BodyPrep
from Animation.Blendshape import MorphShape
from Animation import UniversalRigAdapter
from Dev import mayaiconview
importlib.reload(CreasePlus)
importlib.reload(gs_curvetools)
#===================================== VARIABLES =====================================
TOOL_PATH = os.path.dirname(os.path.abspath(__file__)).replace("\\", "/")
sys.path.append(TOOL_PATH)
TOOL_NAME = "MetaBox"
TOOL_VERSION = "Beta v1.0.0"
TOOL_AUTHOR = "Virtuos"
TOOL_LANG = 'en_US'
SCRIPTS_PATH = os.path.join(TOOL_PATH, "Scripts").replace("\\", "/")
ICONS_PATH = os.path.join(os.path.dirname(TOOL_PATH), "icons").replace("\\", "/")
TOOL_ICON = os.path.join(ICONS_PATH, "logo.png").replace("\\", "/")
DEFAULT_ICON = "commandButton.png"
TOOL_HELP_URL = f"http://10.72.61.59:3000/ArtGroup/{TOOL_NAME}/wiki"
TOOL_WSCL_NAME = "ToolBoxWorkSpaceControl"
MOD_FILE_NAME = f"{TOOL_NAME}.mod"
MAIN_SCRIPT_NAME = f"{TOOL_NAME}.py"
#===================================== UI BUTTONS COMPONENTS =====================================
class RoundedButton(QtWidgets.QPushButton):
def __init__(self, text="", icon=None, color="#D0D0D0", hover_color="#E0E0E0", pressed_color="#C0C0C0"):
super(RoundedButton, self).__init__(text)
if icon:
self.setIcon(icon)
self.setIconSize(QtCore.QSize(24, 24))
self.setMinimumHeight(30)
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};
}}
"""
)
#===================================== GLOBAL FUNCTIONS ===================================
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': {
"DOCUMENT": "DOCUMENT",
"Help": "Help",
"EN": "EN",
"ZH": "ZH",
"zh_CN": "zh_CN",
"Switch Language": "Switch Language",
"Modeling": "Modeling",
"Metahuman": "Metahuman",
"Rigging": "Rigging",
"Animation": "Animation",
"Display": "Display",
"Xray": "Xray",
"Joint Xray": "Joint Xray",
"Manage": "Manage",
"Rename": "Rename",
"Batch Import": "Batch Import",
"Select": "Select",
"Interval Select Edge": "Interval Select Edge",
"Same Position Selector": "Same Position Selector",
"Edge Loop Smart Select": "Edge Loop Smart Select",
"Even Edge Loop": "Even Edge Loop",
"Tools": "Tools",
"Crease Plus": "Crease Plus",
"Speed Cut": "Speed Cut",
"ModIt": "ModIt",
"PlugIt": "PlugIt",
"Zirail": "Zirail",
"Groomer`s Tool": "Groomer`s Tool",
"Edge Sensei": "Edge Sensei",
"Round Inset": "Round Inset",
"Arc Deformer": "Arc Deformer",
"Instant Drag": "Instant Drag",
"Un Bevel": "Un Bevel",
"Align Edge": "Align Edge",
"Extra Curve": "Extra Curve",
"Auto Snap": "Auto Snap",
"Xgen Controller": "Xgen Controller",
"Speed Bend": "Speed Bend",
"Hair Tools": "Hair Tools",
"GS Curve Tools": "GS Curve Tools",
"GS Curve Tools Reset": "GS Curve Tools Reset",
"GS Curve Tools Close": "GS Curve Tools Close",
"UV": "UV",
"UVDeluxe": "UVDeluxe",
"RizomUV Bridge": "RizomUV Bridge",
"UV Set Editor": "UV Set Editor",
"Preparation": "Preparation",
"Body Prepare": "Body Prepare",
"Setup": "Setup",
"Advanced Skeleton": "Advanced Skeleton",
"Select": "Select",
"Anim School Picker": "Anim School Picker",
"DWPicker": "DWPicker",
"Tools": "Tools",
"bhGhost": "bhGhost",
"IK/FK Switch": "IK/FK Switch",
"aTools": "aTools",
"Keyframe Pro": "Keyframe Pro",
"Studio Library": "Studio Library",
"Pose Tools": "Pose Tools",
"Epic Pose Wrangler": "Epic Pose Wrangler",
"Morph Shape": "Morph Shape",
"Universal Rig Adapter": "Universal Rig Adapter",
"Dev": "Dev",
"Dev Tool": "Dev Tool",
"Icon Viewer": "Icon Viewer",
"Import": "Import",
"IK/FK Mocap": "IK/FK Mocap Tool",
"MotionCapHelper": "MotionCap Helper",
"SpringMagic": "Spring Magic",
"Ahoge": "Ahoge",
"QuadRemesher": "Quad Remesher",
"LDMT": "LDMT",
"Simplify": "Simplify"
},
'zh_CN': {
"DOCUMENT": "说明文档",
"Help": "帮助",
"EN": "EN",
"ZH": "ZH",
"zh_CN": "zh_CN",
"Switch Language": "切换语言",
"Modeling": "建模",
"Metahuman": "Metahuman",
"Rigging": "绑定",
"Animation": "动画",
"Display": "显示",
"Xray": "X光显示",
"Joint Xray": "关节X光显示",
"Manage": "管理",
"Rename": "重命名",
"Batch Import": "批量导入",
"Select": "选择",
"Interval Select Edge": "间隔选择边",
"Same Position Selector": "相同位置物体选择器",
"Edge Loop Smart Select": "边缘循环智能选择",
"Even Edge Loop": "等边循环",
"Tools": "工具",
"Crease Plus": "Crease ++",
"Speed Cut": "快速切割",
"ModIt": "ModIt",
"PlugIt": "PlugIt",
"Zirail": "Zirail 拓扑工具",
"Groomer`s Tool": "Groomer 工具",
"Edge Sensei": "边线大师",
"Round Inset": "圆角插入",
"Arc Deformer": "弧形变形器",
"Instant Drag": "吸附放置",
"Un Bevel": "去除倒角",
"Align Edge": "对齐到边",
"Extra Curve": "提取曲线",
"Auto Snap": "自动吸附",
"Xgen Controller": "Xgen 控制器",
"Speed Bend": "快速弯曲",
"Hair Tools": "毛发工具",
"GS Curve Tools": "GS曲线工具",
"GS Curve Tools Reset": "重置",
"GS Curve Tools Close": "关闭",
"UV": "UV",
"UVDeluxe": "UVDeluxe",
"RizomUV Bridge": "RizomUV Bridge",
"UV Set Editor": "UV 编辑器",
"Preparation": "准备",
"Body Prepare": "身体准备",
"Setup": "设置",
"Advanced Skeleton": "高级骨骼",
"Select": "选择",
"Anim School Picker": "Anim School 拾取器",
"DWPicker": "DW 拾取器",
"Tools": "工具",
"bhGhost": "洋葱皮",
"IK/FK Switch": "IK/FK 切换",
"aTools": "aTools",
"Keyframe Pro": "关键帧大师",
"Studio Library": "工作室库",
"Pose Tools": "姿势工具",
"Epic Pose Wrangler": "Epic 姿势变形器",
"Morph Shape": "变形工具",
"Universal Rig Adapter": "通用绑定适配器",
"Dev": "开发",
"Dev Tool": "开发工具",
"Icon Viewer": "图标查看器",
"Import": "导入",
"IK/FK Mocap": "IK/FK 动捕工具",
"MotionCapHelper": "动捕助手",
"SpringMagic": "飘带插件",
"Ahoge": "Ahoge工具",
"QuadRemesher": "重拓扑工具",
"LDMT": "LDMT",
"Simplify": "减面工具"
}
}
#===================================== UI MAIN WINDOW COMPONENTS ===================================
class MainWindow(QtWidgets.QWidget):
def __init__(self, parent=maya_main_window()):
super(MainWindow, self).__init__(parent)
self.setWindowTitle(TOOL_NAME)
self.setObjectName(TOOL_PATH)
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}")
def dock_to_maya(self):
if cmds.workspaceControl(TOOL_WSCL_NAME, exists=True):
cmds.deleteUI(TOOL_WSCL_NAME)
def create_control():
try:
workspace_control = cmds.workspaceControl(
TOOL_WSCL_NAME,
label=TOOL_NAME,
floating=True,
retain=True,
resizeWidth=True,
initialWidth=300,
minimumWidth=300
)
cmds.workspaceControl(TOOL_WSCL_NAME, e=True, resizeWidth=True)
cmds.control(self.objectName(), e=True, p=workspace_control)
cmds.evalDeferred(lambda: cmds.workspaceControl(TOOL_WSCL_NAME, e=True, resizeWidth=True))
except Exception as e:
print(f"Error creating workspace control: {e}")
cmds.evalDeferred(create_control)
#===================================== UI COMPONENTS =====================================
def create_widgets(self):
self.help_btn = QtWidgets.QPushButton(LANG[TOOL_LANG]["DOCUMENT"])
self.help_btn.setToolTip(LANG[TOOL_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 TOOL_LANG == 'zh_CN' else "ZH")
self.lang_btn.setToolTip(LANG[TOOL_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;
}
""")
# Create tabs
self.modeling_tab_btn = RoundedButton(LANG[TOOL_LANG]["Modeling"])
self.metahuman_tab_btn = RoundedButton(LANG[TOOL_LANG]["Metahuman"])
self.rigging_tab_btn = RoundedButton(LANG[TOOL_LANG]["Rigging"])
self.animation_tab_btn = RoundedButton(LANG[TOOL_LANG]["Animation"])
self.dev_tab_btn = RoundedButton(LANG[TOOL_LANG]["Dev"])
# Modeling group widgets
self.modeling_display_group = QtWidgets.QGroupBox(LANG[TOOL_LANG]["Display"] )
self.modeling_xray_btn = RoundedButton(LANG[TOOL_LANG]["Xray"], color="#FFB3BA", hover_color="#FF9DAF", pressed_color="#FF6F61")
self.modeling_joint_xray_btn = RoundedButton(LANG[TOOL_LANG]["Joint Xray"], color="#FFDAA5", hover_color="#FFC78C", pressed_color="#FFC0A1")
self.modeling_manage_group = QtWidgets.QGroupBox(LANG[TOOL_LANG]["Manage"])
self.modeling_rename_btn = RoundedButton(LANG[TOOL_LANG]["Rename"], color="#A4D7E1", hover_color="#A0D8D0", pressed_color="#8CC8C5")
self.modeling_batch_import_btn = RoundedButton(LANG[TOOL_LANG]["Batch Import"], color="#A7C6ED", hover_color="#B2D3F0", pressed_color="#8BB8E0")
self.modeling_select_group = QtWidgets.QGroupBox(LANG[TOOL_LANG]["Select"])
self.modeling_interval_select_edge_btn = RoundedButton(LANG[TOOL_LANG]["Interval Select Edge"], color="#FFEBA1", hover_color="#FFF5B3", pressed_color="#FFE68A")
self.modeling_same_position_selector_btn = RoundedButton(LANG[TOOL_LANG]["Same Position Selector"], color="#FFABAB", hover_color="#FFC3C3", pressed_color="#FF8C8C")
self.modeling_edge_loop_smart_select_btn = RoundedButton(LANG[TOOL_LANG]["Edge Loop Smart Select"], color="#A7C6ED", hover_color="#B2D3F0", pressed_color="#8BB8E0")
self.modeling_even_edge_loop_btn = RoundedButton(LANG[TOOL_LANG]["Even Edge Loop"], color="#FF8C94", hover_color="#FFB3B8", pressed_color="#FF6F7D")
self.modeling_tools_group = QtWidgets.QGroupBox(LANG[TOOL_LANG]["Tools"])
self.modeling_crease_plus_btn = RoundedButton(LANG[TOOL_LANG]["Crease Plus"], color="#FFB74D", hover_color="#FFD54F", pressed_color="#FFA726")
self.modeling_speed_cut_btn = RoundedButton(LANG[TOOL_LANG]["Speed Cut"], color="#FFEBA1", hover_color="#FFF5B3", pressed_color="#FFE68A")
self.modeling_modit_btn = RoundedButton(LANG[TOOL_LANG]["ModIt"], color="#A4D7E1", hover_color="#A0D8D0", pressed_color="#8CC8C5")
self.modeling_plugit_btn = RoundedButton(LANG[TOOL_LANG]["PlugIt"], color="#B39DDB", hover_color="#D1C4E9", pressed_color="#9575CD")
self.modeling_zirail_btn = RoundedButton(LANG[TOOL_LANG]["Zirail"], color="#A7C6ED", hover_color="#B2D3F0", pressed_color="#8BB8E0")
self.modeling_xgtools_btn = RoundedButton(LANG[TOOL_LANG]["Groomer`s Tool"], color="#FFAB40", hover_color="#FFB74D", pressed_color="#FF8F00")
self.modeling_edge_sensei_btn = RoundedButton(LANG[TOOL_LANG]["Edge Sensei"], color="#B2E0B2", hover_color="#C6E6C6", pressed_color="#99D699")
self.modeling_round_inset_btn = RoundedButton(LANG[TOOL_LANG]["Round Inset"], color="#FF8C94", hover_color="#FFB3B8", pressed_color="#FF6F7D")
self.modeling_arc_deformer_btn = RoundedButton(LANG[TOOL_LANG]["Arc Deformer"], color="#E1BEE7", hover_color="#EAB8E4", pressed_color="#D81B60")
self.modeling_speed_bend_btn = RoundedButton(LANG[TOOL_LANG]["Speed Bend"], color="#FFABAB", hover_color="#FF8C8C", pressed_color="#FF6F61")
self.modeling_instant_drag_btn = RoundedButton(LANG[TOOL_LANG]["Instant Drag"], color="#BBDEFB", hover_color="#90CAF9", pressed_color="#64B5F6")
self.modeling_unbevel_btn = RoundedButton(LANG[TOOL_LANG]["Un Bevel"], color="#C8E6C9", hover_color="#A5D6A7", pressed_color="#81C784")
self.modeling_align_edge_btn = RoundedButton(LANG[TOOL_LANG]["Align Edge"], color="#FFCCBC", hover_color="#FFAB91", pressed_color="#FF8A65")
self.modeling_extra_curve_btn = RoundedButton(LANG[TOOL_LANG]["Extra Curve"], color="#E1BEE7", hover_color="#D1C4E9", pressed_color="#BA68C8")
self.modeling_auto_snap_btn = RoundedButton(LANG[TOOL_LANG]["Auto Snap"], color="#FFABAB", hover_color="#FF8C8C", pressed_color="#FF6F61")
self.modeling_xgen_controller_btn = RoundedButton(LANG[TOOL_LANG]["Xgen Controller"], color="#FFEBA1", hover_color="#FFF5B3", pressed_color="#FFE68A")
self.modeling_quad_remesher_btn = RoundedButton(LANG[TOOL_LANG]["QuadRemesher"], color="#BAE1FF", hover_color="#A2D1FF", pressed_color="#8AC4FF")
self.modeling_ldmt_btn = RoundedButton(LANG[TOOL_LANG]["LDMT"], color="#BAE1FF", hover_color="#A2D1FF", pressed_color="#8AC4FF")
self.modeling_simplify_btn = RoundedButton(LANG[TOOL_LANG]["Simplify"], color="#BAE1FF", hover_color="#A2D1FF", pressed_color="#8AC4FF")
self.modeling_gs_curve_tools_group = QtWidgets.QGroupBox(LANG[TOOL_LANG]["Hair Tools"])
self.modeling_gs_curve_tools_btn = RoundedButton(LANG[TOOL_LANG]["GS Curve Tools"], color="#C8E6C9", hover_color="#A5D6A7", pressed_color="#81C784")
self.modeling_reset_gs_curve_tools_btn = RoundedButton(LANG[TOOL_LANG]["GS Curve Tools Reset"], color="#FFEBA1", hover_color="#FFF5B3", pressed_color="#FFE68A")
self.modeling_close_gs_curve_tools_btn = RoundedButton(LANG[TOOL_LANG]["GS Curve Tools Close"], color="#FFCCBC", hover_color="#FFAB91", pressed_color="#FF8A65")
self.modeling_ahoge_btn = RoundedButton(LANG[TOOL_LANG]["Ahoge"], color="#BAE1FF", hover_color="#A2D1FF", pressed_color="#8AC4FF")
self.modeling_uv_group = QtWidgets.QGroupBox(LANG[TOOL_LANG]["UV"])
self.modeling_uvdeluxe_btn = RoundedButton(LANG[TOOL_LANG]["UVDeluxe"], color="#A7C6ED", hover_color="#B2D3F0", pressed_color="#8BB8E0")
self.modeling_rizom_uv_bridge_btn = RoundedButton(LANG[TOOL_LANG]["RizomUV Bridge"], color="#FFABAB", hover_color="#FFC3C3", pressed_color="#FF8C8C")
self.modeling_uv_set_editor_btn = RoundedButton(LANG[TOOL_LANG]["UV Set Editor"], color="#FFEBA1", hover_color="#FFF5B3", pressed_color="#FFE68A")
# Metahuman group widgets
self.metahuman_preparation_group = QtWidgets.QGroupBox(LANG[TOOL_LANG]["Preparation"])
self.metahuman_body_prepare_btn = RoundedButton(LANG[TOOL_LANG]["Body Prepare"], color="#FFABAB", hover_color="#FF6F6F", pressed_color="#FF8C8C")
self.metahuman_import_group = QtWidgets.QGroupBox(LANG[TOOL_LANG]["Import"])
self.metahuman_batch_import_btn = RoundedButton(LANG[TOOL_LANG]["Batch Import"], color="#A7C6ED", hover_color="#B2D3F0", pressed_color="#8BB8E0")
# Rigging group widgets
self.rigging_setup_group = QtWidgets.QGroupBox(LANG[TOOL_LANG]["Setup"])
self.rigging_advanced_skeleton_btn = RoundedButton(LANG[TOOL_LANG]["Advanced Skeleton"], color="#FFDAA5", hover_color="#FFC78C", pressed_color="#FFC0A1")
# Animation group widgets
self.animation_select_group = QtWidgets.QGroupBox(LANG[TOOL_LANG]["Select"])
self.animation_animschool_picker_btn = RoundedButton(LANG[TOOL_LANG]["Anim School Picker"], color="#FFB3BA", hover_color="#FF9DAF", pressed_color="#FF8C94")
self.animation_dwpicker_btn = RoundedButton(LANG[TOOL_LANG]["DWPicker"], color="#A0D8D0", hover_color="#8CC8C5", pressed_color="#7FBFBF")
self.animation_tools_group = QtWidgets.QGroupBox(LANG[TOOL_LANG]["Tools"])
self.animation_bhghost_btn = RoundedButton(LANG[TOOL_LANG]["bhGhost"], color="#FFDAA5", hover_color="#FFC78C", pressed_color="#FFC0A1")
self.animation_ikfk_switch_btn = RoundedButton(LANG[TOOL_LANG]["IK/FK Switch"], color="#B2E1D4", hover_color="#A0D8D0", pressed_color="#8CC8C5")
self.animation_atools_btn = RoundedButton(LANG[TOOL_LANG]["aTools"], color="#FFB3BA", hover_color="#FF9DAF", pressed_color="#FF8C94")
self.animation_keyframepro_btn = RoundedButton(LANG[TOOL_LANG]["Keyframe Pro"], color="#FFDAA5", hover_color="#FFC78C", pressed_color="#FFC0A1")
self.animation_studiolibrary_btn = RoundedButton(LANG[TOOL_LANG]["Studio Library"], color="#A0D8D0", hover_color="#8CC8C5", pressed_color="#7FBFBF")
# self.animation_ikfk_mocap_btn = RoundedButton(LANG[TOOL_LANG]["IK/FK Mocap"], color="#FFB3BA", hover_color="#FF9DAF", pressed_color="#FF8C94")
self.animation_motioncap_helper_btn = RoundedButton(LANG[TOOL_LANG]["MotionCapHelper"], color="#FFB3BA", hover_color="#FF9DAF", pressed_color="#FF8C94")
self.animation_spring_magic_btn = RoundedButton(LANG[TOOL_LANG]["SpringMagic"], color="#FFB3BA", hover_color="#FF9DAF", pressed_color="#FF8C94")
self.animation_pose_group = QtWidgets.QGroupBox(LANG[TOOL_LANG]["Pose Tools"])
self.animation_epic_pose_wrangler_btn = RoundedButton(LANG[TOOL_LANG]["Epic Pose Wrangler"], color="#FFB3BA", hover_color="#FF9DAF", pressed_color="#FF8C94")
self.animation_morph_shape_btn = RoundedButton(LANG[TOOL_LANG]["Morph Shape"], color="#FFDAA5", hover_color="#FFC78C", pressed_color="#FFC0A1")
self.animation_universal_rig_adapter_btn = RoundedButton(LANG[TOOL_LANG]["Universal Rig Adapter"], color="#A0D8D0", hover_color="#8CC8C5", pressed_color="#7FBFBF")
# Dev group widgets
self.dev_tools_group = QtWidgets.QGroupBox(LANG[TOOL_LANG]["Dev Tool"])
self.dev_icon_viewer_btn = RoundedButton(LANG[TOOL_LANG]["Icon Viewer"], color="#FFDAA5", hover_color="#FFC78C", pressed_color="#FFC0A1")
def create_layouts(self):
main_layout = QtWidgets.QVBoxLayout(self)
main_layout.setContentsMargins(2, 2, 2, 2)
# Resizable by dragging
main_layout.setStretch(0, 1)
# Tabs Layout
tabs_layout = QtWidgets.QTabWidget(self)
main_layout.addWidget(tabs_layout)
#===================================MODELING TAB===================================
modeling_tab = QtWidgets.QWidget()
modeling_layout = QtWidgets.QHBoxLayout(modeling_tab)
# Scroll area
modeling_scroll_area = QtWidgets.QScrollArea()
modeling_scroll_area.setWidgetResizable(True)
modeling_scroll_area_content = QtWidgets.QWidget()
modeling_scroll_area_layout = QtWidgets.QVBoxLayout(modeling_scroll_area_content)
modeling_scroll_area.setWidget(modeling_scroll_area_content)
# Display
modeling_scroll_area_layout.addWidget(self.modeling_display_group)
modeling_display_layout = QtWidgets.QGridLayout(self.modeling_display_group)
modeling_display_layout.addWidget(self.modeling_xray_btn, 0, 0)
modeling_display_layout.addWidget(self.modeling_joint_xray_btn, 0, 1)
# Manage
modeling_scroll_area_layout.addWidget(self.modeling_manage_group)
modeling_manage_layout = QtWidgets.QVBoxLayout(self.modeling_manage_group)
modeling_manage_layout.addWidget(self.modeling_rename_btn)
modeling_manage_layout.addWidget(self.modeling_batch_import_btn)
# Select
modeling_scroll_area_layout.addWidget(self.modeling_select_group)
modeling_select_layout = QtWidgets.QVBoxLayout(self.modeling_select_group)
modeling_select_layout.addWidget(self.modeling_interval_select_edge_btn)
modeling_select_layout.addWidget(self.modeling_same_position_selector_btn)
modeling_select_layout.addWidget(self.modeling_edge_loop_smart_select_btn)
modeling_select_layout.addWidget(self.modeling_even_edge_loop_btn)
# Tools
modeling_scroll_area_layout.addWidget(self.modeling_tools_group)
modeling_tools_layout = QtWidgets.QGridLayout(self.modeling_tools_group)
modeling_tools_layout.addWidget(self.modeling_crease_plus_btn, 0, 0)
modeling_tools_layout.addWidget(self.modeling_speed_cut_btn, 0, 1)
modeling_tools_layout.addWidget(self.modeling_modit_btn, 1, 0)
modeling_tools_layout.addWidget(self.modeling_plugit_btn, 1, 1)
modeling_tools_layout.addWidget(self.modeling_zirail_btn, 2, 0)
modeling_tools_layout.addWidget(self.modeling_xgtools_btn, 2, 1)
modeling_tools_layout.addWidget(self.modeling_edge_sensei_btn, 3, 0)
modeling_tools_layout.addWidget(self.modeling_round_inset_btn, 3, 1)
modeling_tools_layout.addWidget(self.modeling_arc_deformer_btn, 4, 0)
modeling_tools_layout.addWidget(self.modeling_speed_bend_btn, 4, 1)
modeling_tools_layout.addWidget(self.modeling_instant_drag_btn, 5, 0)
modeling_tools_layout.addWidget(self.modeling_unbevel_btn, 5, 1)
modeling_tools_layout.addWidget(self.modeling_align_edge_btn, 6, 0)
modeling_tools_layout.addWidget(self.modeling_extra_curve_btn, 6, 1)
modeling_tools_layout.addWidget(self.modeling_auto_snap_btn, 7, 0)
modeling_tools_layout.addWidget(self.modeling_xgen_controller_btn, 7, 1)
modeling_tools_layout.addWidget(self.modeling_quad_remesher_btn, 8, 0)
# modeling_tools_layout.addWidget(self.modeling_simplify_btn, 8, 1)
# modeling_tools_layout.addWidget(self.modeling_ldmt_btn, 9, 0)
# GS Curve Tools
modeling_scroll_area_layout.addWidget(self.modeling_gs_curve_tools_group)
modeling_gs_curve_tools_layout = QtWidgets.QVBoxLayout(self.modeling_gs_curve_tools_group)
modeling_gs_curve_tools_layout.addWidget(self.modeling_gs_curve_tools_btn)
modeling_gs_curve_tools_layout.addWidget(self.modeling_reset_gs_curve_tools_btn)
modeling_gs_curve_tools_layout.addWidget(self.modeling_close_gs_curve_tools_btn)
modeling_gs_curve_tools_layout.addWidget(self.modeling_ahoge_btn)
# UV
modeling_scroll_area_layout.addWidget(self.modeling_uv_group)
modeling_uv_layout = QtWidgets.QVBoxLayout(self.modeling_uv_group)
modeling_uv_layout.addWidget(self.modeling_uv_set_editor_btn)
modeling_uv_layout.addWidget(self.modeling_uvdeluxe_btn)
modeling_uv_layout.addWidget(self.modeling_rizom_uv_bridge_btn)
# Add the scroll area to the main layout
modeling_layout.addWidget(modeling_scroll_area)
tabs_layout.addTab(modeling_tab, "Modeling")
#===================================METAHUMAN TAB===================================
metahuman_tab = QtWidgets.QWidget()
metahuman_layout = QtWidgets.QVBoxLayout(metahuman_tab)
# Scroll area
metahuman_scroll_area = QtWidgets.QScrollArea()
metahuman_scroll_area.setWidgetResizable(True)
metahuman_scroll_area_content = QtWidgets.QWidget()
metahuman_scroll_area_layout = QtWidgets.QVBoxLayout(metahuman_scroll_area_content)
metahuman_scroll_area.setWidget(metahuman_scroll_area_content)
# Add all buttons and groups to the scroll area
metahuman_scroll_area_layout.addWidget(self.metahuman_preparation_group)
metahuman_preparation_layout = QtWidgets.QVBoxLayout(self.metahuman_preparation_group)
metahuman_preparation_layout.addWidget(self.metahuman_body_prepare_btn)
# Add Import group layout
metahuman_scroll_area_layout.addWidget(self.metahuman_import_group)
metahuman_import_layout = QtWidgets.QVBoxLayout(self.metahuman_import_group)
metahuman_import_layout.addWidget(self.metahuman_batch_import_btn)
# Add the scroll area to the main layout
metahuman_layout.addWidget(metahuman_scroll_area)
tabs_layout.addTab(metahuman_tab, "Metahuman")
#===================================RIGGING TAB===================================
rigging_tab = QtWidgets.QWidget()
rigging_layout = QtWidgets.QVBoxLayout(rigging_tab)
# Scroll area
rigging_scroll_area = QtWidgets.QScrollArea()
rigging_scroll_area.setWidgetResizable(True)
rigging_scroll_area_content = QtWidgets.QWidget()
rigging_scroll_area_layout = QtWidgets.QVBoxLayout(rigging_scroll_area_content)
rigging_scroll_area.setWidget(rigging_scroll_area_content)
# Add all buttons and groups to the scroll area
rigging_scroll_area_layout.addWidget(self.rigging_setup_group)
rigging_setup_layout = QtWidgets.QVBoxLayout(self.rigging_setup_group)
rigging_setup_layout.addWidget(self.rigging_advanced_skeleton_btn)
# Add the scroll area to the main layout
rigging_layout.addWidget(rigging_scroll_area)
tabs_layout.addTab(rigging_tab, "Rigging")
#===================================ANIMATION TAB===================================
animation_tab = QtWidgets.QWidget()
animation_layout = QtWidgets.QVBoxLayout(animation_tab)
# Scroll area
animation_scroll_area = QtWidgets.QScrollArea()
animation_scroll_area.setWidgetResizable(True)
animation_scroll_area_content = QtWidgets.QWidget()
animation_scroll_area_layout = QtWidgets.QVBoxLayout(animation_scroll_area_content)
animation_scroll_area.setWidget(animation_scroll_area_content)
# Add all buttons and groups to the scroll area
animation_scroll_area_layout.addWidget(self.animation_select_group)
animation_select_layout = QtWidgets.QVBoxLayout(self.animation_select_group)
animation_select_layout.addWidget(self.animation_animschool_picker_btn)
animation_select_layout.addWidget(self.animation_dwpicker_btn)
animation_scroll_area_layout.addWidget(self.animation_tools_group)
animation_tools_layout = QtWidgets.QGridLayout(self.animation_tools_group)
animation_tools_layout.addWidget(self.animation_bhghost_btn, 0, 0)
animation_tools_layout.addWidget(self.animation_ikfk_switch_btn, 0, 1)
animation_tools_layout.addWidget(self.animation_atools_btn, 1, 0)
animation_tools_layout.addWidget(self.animation_keyframepro_btn, 1, 1)
animation_tools_layout.addWidget(self.animation_studiolibrary_btn, 2, 0)
# animation_tools_layout.addWidget(self.animation_ikfk_mocap_btn, 2, 1)
animation_tools_layout.addWidget(self.animation_motioncap_helper_btn, 2, 1)
animation_tools_layout.addWidget(self.animation_spring_magic_btn, 3, 0)
animation_scroll_area_layout.addWidget(self.animation_pose_group)
animation_pose_layout = QtWidgets.QVBoxLayout(self.animation_pose_group)
animation_pose_layout.addWidget(self.animation_epic_pose_wrangler_btn)
animation_pose_layout.addWidget(self.animation_morph_shape_btn)
animation_pose_layout.addWidget(self.animation_universal_rig_adapter_btn)
# Add the scroll area to the main layout
animation_layout.addWidget(animation_scroll_area)
tabs_layout.addTab(animation_tab, "Animation")
#===================================DEV TAB===================================
dev_tab = QtWidgets.QWidget()
dev_layout = QtWidgets.QVBoxLayout(dev_tab)
# Scroll area
dev_scroll_area = QtWidgets.QScrollArea()
dev_scroll_area.setWidgetResizable(True)
dev_scroll_area_content = QtWidgets.QWidget()
dev_scroll_area_layout = QtWidgets.QVBoxLayout(dev_scroll_area_content)
dev_scroll_area.setWidget(dev_scroll_area_content)
# Add all buttons and groups to the scroll area
dev_scroll_area_layout.addWidget(self.dev_tools_group)
dev_tools_layout = QtWidgets.QVBoxLayout(self.dev_tools_group)
dev_tools_layout.addWidget(self.dev_icon_viewer_btn)
# Add the scroll area to the main layout
dev_layout.addWidget(dev_scroll_area)
tabs_layout.addTab(dev_tab, "Dev")
# change bottom layout
bottom_layout = QtWidgets.QHBoxLayout()
# create icon label
icon_label = QtWidgets.QLabel()
if os.path.exists(TOOL_ICON):
icon = QtGui.QPixmap(TOOL_ICON).scaled(24, 24, QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation)
icon_label.setPixmap(icon)
else:
print(f"Warning: Icon file '{TOOL_ICON}' does not exist.")
# add icon label to bottom layout
bottom_layout.addWidget(icon_label)
# add version information label
version_label = QtWidgets.QLabel(f"{TOOL_VERSION}")
version_label.setStyleSheet("color: gray; font-size: 12px;")
bottom_layout.addWidget(version_label)
# add a stretchable space to push the help and language buttons to the right
bottom_layout.addStretch()
# add help and language buttons
bottom_layout.addWidget(self.help_btn)
bottom_layout.addWidget(self.lang_btn)
# add bottom layout to main layout
main_layout.addLayout(bottom_layout)
def create_connections(self):
# Modeling tab connections
self.modeling_xray_btn.clicked.connect(self.run_xray)
self.modeling_joint_xray_btn.clicked.connect(self.run_joint_xray)
self.modeling_rename_btn.clicked.connect(self.run_rename)
self.modeling_batch_import_btn.clicked.connect(self.run_batch_import)
self.modeling_interval_select_edge_btn.clicked.connect(self.run_select_edge)
self.modeling_same_position_selector_btn.clicked.connect(self.run_same_position_selector)
self.modeling_edge_loop_smart_select_btn.clicked.connect(self.run_edge_loop_smart_select)
self.modeling_even_edge_loop_btn.clicked.connect(self.run_even_edge_loop)
self.modeling_crease_plus_btn.clicked.connect(self.run_crease_plus)
self.modeling_speed_cut_btn.clicked.connect(self.run_speed_cut)
self.modeling_modit_btn.clicked.connect(self.run_modit)
self.modeling_plugit_btn.clicked.connect(self.run_plugit)
self.modeling_zirail_btn.clicked.connect(self.run_zirail)
self.modeling_xgtools_btn.clicked.connect(self.run_xgtools)
self.modeling_edge_sensei_btn.clicked.connect(self.run_edge_sensei)
self.modeling_round_inset_btn.clicked.connect(self.run_round_inset)
self.modeling_arc_deformer_btn.clicked.connect(self.run_arc_deformer)
self.modeling_instant_drag_btn.clicked.connect(self.run_instant_drag)
self.modeling_unbevel_btn.clicked.connect(self.run_unbevel)
self.modeling_speed_bend_btn.clicked.connect(self.run_speed_bend)
self.modeling_align_edge_btn.clicked.connect(self.run_align_edge)
self.modeling_extra_curve_btn.clicked.connect(self.run_extra_curve)
self.modeling_auto_snap_btn.clicked.connect(self.run_auto_snap)
self.modeling_xgen_controller_btn.clicked.connect(self.run_xgen_controller)
self.modeling_quad_remesher_btn.clicked.connect(self.run_quad_remesher)
self.modeling_ldmt_btn.clicked.connect(self.run_ldmt)
self.modeling_simplify_btn.clicked.connect(self.run_simplify)
self.modeling_gs_curve_tools_btn.clicked.connect(self.run_gs_curve_tools)
self.modeling_reset_gs_curve_tools_btn.clicked.connect(self.reset_gs_curve_tools)
self.modeling_close_gs_curve_tools_btn.clicked.connect(self.stop_gs_curve_tools)
self.modeling_ahoge_btn.clicked.connect(self.run_ahoge)
self.modeling_uv_set_editor_btn.clicked.connect(self.run_uv_set_editor)
self.modeling_uvdeluxe_btn.clicked.connect(self.run_uvdeluxe)
self.modeling_rizom_uv_bridge_btn.clicked.connect(self.run_rizom_uv_bridge)
# Metahuman tab connections
self.metahuman_body_prepare_btn.clicked.connect(self.run_body_prepare)
self.metahuman_batch_import_btn.clicked.connect(self.run_batch_import)
# Rigging tab connections
self.rigging_advanced_skeleton_btn.clicked.connect(self.run_advanced_skeleton)
# Animation tab connections
self.animation_animschool_picker_btn.clicked.connect(self.run_anim_school_picker)
self.animation_dwpicker_btn.clicked.connect(self.run_dwpicker)
self.animation_bhghost_btn.clicked.connect(self.run_bhghost)
self.animation_ikfk_switch_btn.clicked.connect(self.run_ik_fk_switch)
self.animation_atools_btn.clicked.connect(self.open_aTools)
self.animation_keyframepro_btn.clicked.connect(self.open_keyframe_pro)
self.animation_studiolibrary_btn.clicked.connect(self.open_studio_library)
# self.animation_ikfk_mocap_btn.clicked.connect(self.run_ikfk_mocap)
self.animation_motioncap_helper_btn.clicked.connect(self.run_motioncap_helper)
self.animation_spring_magic_btn.clicked.connect(self.run_spring_magic)
self.animation_epic_pose_wrangler_btn.clicked.connect(self.open_epic_pose_wrangler)
self.animation_morph_shape_btn.clicked.connect(self.run_morph_shape)
self.animation_universal_rig_adapter_btn.clicked.connect(self.run_universal_rig_adapter)
# Dev tab connections
self.dev_icon_viewer_btn.clicked.connect(self.run_icon_viewer)
# connect help button
self.help_btn.clicked.connect(self.show_help)
# connect language switch button
self.lang_btn.clicked.connect(self.toggle_language)
#========================================================================== FUNCTIONS ==========================================================================
def show_error(self, task, e):
ERROR_MESSAGE = f"Error occurred while running {task}: {e}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
# Modeling Functions
# ****************************************************************************************************************
# Display
def run_xray(self, *args):
try:
result = cmds.modelEditor('modelPanel4', q=True, xr=True)
cmds.modelEditor('modelPanel4', e=True, xr=not result)
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running Xray: {e}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
def run_joint_xray(self, *args):
try:
result = cmds.modelEditor('modelPanel4', q=True, jx=True)
cmds.modelEditor('modelPanel4', e=True, jx=not result)
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running XrayJoint: {e}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
# Manage
def run_rename(self, *args):
try:
Rename_Path = os.path.normpath(os.path.join(TOOL_PATH, 'Modeling', 'Manage', 'Rename.py')).replace('\\', '/')
sys.path.append(Rename_Path)
Rename.UI()
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running Rename: {e}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
def run_batch_import(self, *args):
try:
BatchImport_Path = os.path.normpath(os.path.join(TOOL_PATH, 'Metahuman', 'Custom', 'BatchImport.py')).replace('\\', '/')
if BatchImport_Path not in sys.path:
sys.path.append(BatchImport_Path)
from Metahuman.Custom import BatchImport
BatchImport.run()
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running Batch Import: {e}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
# Edit
def run_crease_plus(self, *args):
try:
crease_plus_dir = os.path.normpath(os.path.join(TOOL_PATH, 'Modeling', 'Edit', 'CreasePlus')).replace('\\', '/')
print(f"CreasePlus directory: {crease_plus_dir}")
if crease_plus_dir not in sys.path:
sys.path.append(crease_plus_dir)
from Modeling.Edit.CreasePlus import CreasePlusMain
CreasePlusMain.start()
print("CreasePlus loaded successfully")
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running Crease Plus: {e}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
print(f"Detailed error: {traceback.format_exc()}")
def run_speed_cut(self, *args):
try:
SpeedCut.run()
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running Speed Cut: {e}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
def run_gs_curve_tools(self, *args):
try:
gs_curvetools_path = os.path.normpath(os.path.join(TOOL_PATH, 'Modeling', 'Edit', 'gs_curvetools')).replace('\\', '/')
if gs_curvetools_path not in sys.path:
sys.path.insert(0, gs_curvetools_path)
gs_curvetools_sub_path = [
os.path.join(gs_curvetools_path, 'fonts').replace('\\', '/'),
os.path.join(gs_curvetools_path, 'icons').replace('\\', '/'),
os.path.join(gs_curvetools_path, 'plugins').replace('\\', '/'),
os.path.join(gs_curvetools_path, 'utils').replace('\\', '/'),
os.path.join(gs_curvetools_path, 'constants').replace('\\', '/'),
os.path.join(gs_curvetools_path, 'core').replace('\\', '/'),
os.path.join(gs_curvetools_path, 'main').replace('\\', '/'),
os.path.join(gs_curvetools_path, 'ui').replace('\\', '/'),
os.path.join(gs_curvetools_path, 'uv_editor').replace('\\', '/')
]
for path in gs_curvetools_sub_path:
if path not in sys.path:
sys.path.insert(0, path)
from Modeling.Edit.gs_curvetools import main as ct_main
# Run the main function
ct_main.main()
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running GS Curve Tools: {str(e)}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
print(f"Detailed error: {traceback.format_exc()}")
def stop_gs_curve_tools(self, *args):
try:
gs_curvetools_path = os.path.normpath(os.path.join(TOOL_PATH, 'Modeling', 'Edit', 'gs_curvetools')).replace('\\', '/')
if gs_curvetools_path not in sys.path:
sys.path.insert(0, gs_curvetools_path)
from Modeling.Edit.gs_curvetools.utils import utils as ct_ut
ct_ut.stopUI()
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running GS Curve Tools: {str(e)}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
print(f"Detailed error: {traceback.format_exc()}")
def reset_gs_curve_tools(self, *args):
try:
gs_curvetools_path = os.path.normpath(os.path.join(TOOL_PATH, 'Modeling', 'Edit', 'gs_curvetools')).replace('\\', '/')
if gs_curvetools_path not in sys.path:
sys.path.insert(0, gs_curvetools_path)
from Modeling.Edit.gs_curvetools.utils import utils as ct_ut
ct_ut.resetOptionVars()
def __getMayaOS():
"""Get Maya version and parent OS"""
maya = str(cmds.about(api=1))[:4]
os = str(cmds.about(os=1))
return [int(maya), os]
logger = ct_ut.Logger()
MAYA_VER = __getMayaOS()[0]
LOGGER = logger.logger
if MAYA_VER >= 2018:
ct_ut.stopUI(True)
# Reload all files
gs_curvetools_subpaths = [
os.path.join(gs_curvetools_path, 'constants').replace('\\', '/'),
os.path.join(gs_curvetools_path, 'core').replace('\\', '/'),
os.path.join(gs_curvetools_path, 'main').replace('\\', '/'),
os.path.join(gs_curvetools_path, 'ui').replace('\\', '/'),
os.path.join(gs_curvetools_path, 'uv_editor').replace('\\', '/'),
os.path.join(gs_curvetools_path, 'utils').replace('\\', '/'),
os.path.join(gs_curvetools_path, 'utils', 'gs_math').replace('\\', '/'),
os.path.join(gs_curvetools_path, 'utils', 'style').replace('\\', '/'),
os.path.join(gs_curvetools_path, 'utils', 'tooltips').replace('\\', '/'),
os.path.join(gs_curvetools_path, 'utils', 'utils').replace('\\', '/'),
os.path.join(gs_curvetools_path, 'utils', 'wrap').replace('\\', '/')
]
for subpath in gs_curvetools_subpaths:
if subpath not in sys.path:
sys.path.insert(0, subpath)
from Modeling.Edit.gs_curvetools import main as ct_main
ct_main.main()
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running GS Curve Tools: {str(e)}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
print(f"Detailed error: {traceback.format_exc()}")
def run_modit(self, *args):
try:
modit_path = os.path.normpath(os.path.join(TOOL_PATH, 'Modeling', 'Edit', 'ModIt')).replace('\\', '/')
modlit_sub_paths = [
os.path.join(modit_path, 'Classes'),
os.path.join(modit_path, 'Icons'),
os.path.join(modit_path, 'Mesh'),
os.path.join(modit_path, 'Preferences'),
os.path.join(modit_path, 'Shaders'),
os.path.join(modit_path, 'Tools')
]
for path in modlit_sub_paths:
if path not in sys.path:
sys.path.append(path)
os.environ['MAYA_PLUG_IN_PATH'] = os.pathsep.join(modlit_sub_paths)
modit_ui_path = os.path.join(modit_path, 'ModIt_UI.py').replace('\\', '/')
if modit_ui_path not in sys.path:
sys.path.append(os.path.dirname(modit_ui_path))
from Modeling.Edit.ModIt import ModIt_UI
importlib.reload(ModIt_UI)
ModIt_UI
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running ModIt: {e}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
def run_plugit(self, *args):
try:
PlugIt_Path = os.path.normpath(os.path.join(TOOL_PATH, 'Modeling', 'Edit', 'PlugIt')).replace('\\', '/')
plugIt_sub_paths = [
os.path.join(PlugIt_Path, 'Icons'),
os.path.join(PlugIt_Path, 'LIBRARY'),
os.path.join(PlugIt_Path, 'PlugIt_Creation'),
os.path.join(PlugIt_Path, 'Preferences'),
os.path.join(PlugIt_Path, 'Tools'),
]
for path in plugIt_sub_paths:
if path not in sys.path:
sys.path.append(path)
os.environ['MAYA_PLUG_IN_PATH'] = os.pathsep.join(plugIt_sub_paths)
plugIt_ui_path = os.path.join(PlugIt_Path, 'PlugIt_UI.py').replace('\\', '/')
if plugIt_ui_path not in sys.path:
sys.path.append(os.path.dirname(plugIt_ui_path))
from Modeling.Edit.PlugIt import PlugIt_UI
importlib.reload(PlugIt_UI)
PlugIt_UI.showUI()
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running PlugIt: {e}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
def run_xgtools(self, *args):
try:
import maya.cmds as cmds
print("Successfully imported maya.cmds")
import sys
import os
import traceback
XGTC_PARENT_PATH = os.path.join(TOOL_PATH, 'Modeling', 'Edit')
if XGTC_PARENT_PATH not in sys.path:
sys.path.insert(0, XGTC_PARENT_PATH)
xgtc_path = os.path.join(XGTC_PARENT_PATH, 'xgtc').replace('\\', '/')
if xgtc_path not in sys.path:
sys.path.insert(0, xgtc_path)
xgtc_scripts_path = os.path.join(xgtc_path, 'scripts').replace('\\', '/')
if xgtc_scripts_path not in sys.path:
sys.path.insert(0, xgtc_scripts_path)
xgtc_icons_path = os.path.join(xgtc_path, 'icons').replace('\\', '/')
if xgtc_icons_path not in sys.path:
sys.path.insert(0, xgtc_icons_path)
from Modeling.Edit.xgtc.scripts import xgToolsUI_user_sub
print("Successfully imported XGTools modules")
xgToolsUI_user_sub.xgToolsUI()
except ImportError as e:
ERROR_MESSAGE = f"Error importing modules for XGTools: {str(e)}"
print(ERROR_MESSAGE)
cmds.warning(ERROR_MESSAGE)
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running XGTools: {e}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
def run_zirail(self, *args):
try:
# Get Maya version
MAYA_VERSION = cmds.about(version=True).split()[0]
if MAYA_VERSION == '2018' or MAYA_VERSION == '2019' or MAYA_VERSION == '2020':
ZIRAIL_PATH = os.path.join(TOOL_PATH, 'Modeling', 'Edit', 'ziRail', '2018_2020').replace('\\', '/')
ZIRAIL_PLUGIN_PATH = os.path.join(TOOL_PATH, 'Modeling', 'Edit', 'ziRail', '2018_2020', 'plug-ins').replace('\\', '/')
for plugin in [f'ziRail_{MAYA_VERSION}.mll', f'ziWireframeViewport_{MAYA_VERSION}.mll']:
plugin_path = os.path.join(ZIRAIL_PLUGIN_PATH, plugin)
if os.path.exists(plugin_path):
if not cmds.pluginInfo(plugin_path, query=True, loaded=True):
cmds.loadPlugin(plugin_path)
else:
print(f"Warning: Plugin file does not exist: {plugin_path}")
elif MAYA_VERSION == '2022' or MAYA_VERSION == '2023':
ZIRAIL_PATH = os.path.join(TOOL_PATH, 'Modeling', 'Edit', 'ziRail', '2022_2023').replace('\\', '/')
ZIRAIL_PLUGIN_PATH = os.path.join(TOOL_PATH, 'Modeling', 'Edit', 'ziRail', '2022_2023', 'plug-ins').replace('\\', '/')
for plugin in [f'ziRail_{MAYA_VERSION}.mll', f'ziWireframeViewport_{MAYA_VERSION}.mll']:
plugin_path = os.path.join(ZIRAIL_PLUGIN_PATH, plugin)
if os.path.exists(plugin_path):
if not cmds.pluginInfo(plugin_path, query=True, loaded=True):
cmds.loadPlugin(plugin_path)
else:
print(f"Warning: Plugin file does not exist: {plugin_path}")
if os.path.exists(ZIRAIL_PLUGIN_PATH):
os.environ['MAYA_PLUG_IN_PATH'] = os.pathsep.join([os.environ.get('MAYA_PLUG_IN_PATH', ''), ZIRAIL_PLUGIN_PATH])
else:
ERROR_MESSAGE = f"Error occurred while running ziRail: Maya version {MAYA_VERSION} is not supported"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
return
# Check if ZIRAIL_PATH exists before adding to sys.path
if os.path.exists(ZIRAIL_PATH) and ZIRAIL_PATH not in sys.path:
sys.path.insert(0, ZIRAIL_PATH)
# Import and run the appropriate ziRail module
if MAYA_VERSION in ['2018', '2019', '2020']:
zi_rail = importlib.import_module(f'Modeling.Edit.ziRail.2018_2020.zi_rail')
elif MAYA_VERSION in ['2022', '2023']:
zi_rail = importlib.import_module(f'Modeling.Edit.ziRail.2022_2023.zi_rail')
else:
ERROR_MESSAGE = f"Error occurred while running ziRail: Maya version {MAYA_VERSION} is not supported"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
return
importlib.reload(zi_rail)
zi_rail.main()
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running ziRail: {e}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
def run_edge_sensei(self, *args):
try:
EdgeSensei.run()
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running Edge Sensei: {e}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
def run_even_edge_loop(self, *args):
try:
EvenEdgeLoop.run()
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running Even Edge Loop: {e}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
def run_speed_bend(self, *args):
try:
SpeedBend.run()
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running Speed Bend: {e}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
def run_poly_fold(self, *args):
try:
PolyFold.run()
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running Poly Fold: {e}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
def run_round_inset(self, *args):
try:
RoundInset.run()
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running Round Inset: {e}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
def run_arc_deformer(self, *args):
try:
ArcDeformer.run()
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running Arc Deformer: {e}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
def run_instant_drag(self, *args):
try:
InstantDrag.run()
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running Instant Drag: {e}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
def run_unbevel(self, *args):
try:
UnBevel.run()
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running UnBevel: {e}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
def run_extra_curve(self, *args):
try:
mel.eval('polyToCurve -form 2 -degree 3 -conformToSmoothMeshPreview 1')
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running ExtractCurve: {e}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
def run_auto_snap(self, *args):
try:
AutoSnap.cmd()
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running ExtractCurve: {e}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
def run_xgen_controller(self, *args):
try:
XgenController.create_window()
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running ExtractCurve: {e}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
# Select
def run_edge_loop_smart_select(self, *args):
try:
EdgeLoopSmartSelect.run()
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running Edge Loop Smart Select: {e}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
def run_select_edge(self, *args):
try:
IntervalSelectEdge.show()
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running Interval Select Edge: {e}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
def run_same_position_selector(self, *args):
try:
SamePositionSelector.show()
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running SamePositionSelector: {e}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
def run_align_edge(self, *args):
try:
AlignEdge.run()
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running Align Edge: {e}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
# UV
def run_uv_set_editor(self, *args):
try:
UVSetEditor.show()
except Exception as e:
ERROR_MESSAGE = f"Error occurred while opening UV Set Editor: {e}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
def run_uvdeluxe(self, *args):
try:
from Modeling.UV.UVDeluxe import uvdeluxe
uvdeluxe.createUI()
except Exception as e:
ERROR_MESSAGE = f"Error occurred while opening UVDeluxe: {e}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
def run_rizom_uv_bridge(self, *args):
try:
RIZOMUV_PATH = os.path.normpath(os.path.join(TOOL_PATH, 'Modeling', 'UV', 'RizomUVBridge')).replace('\\', '/')
if RIZOMUV_PATH not in sys.path:
sys.path.insert(0, RIZOMUV_PATH)
RIZOMUV_LUA_PATH = os.path.join(RIZOMUV_PATH, 'RizomUVBridge.lua').replace('\\', '/')
if RIZOMUV_LUA_PATH not in sys.path:
sys.path.insert(0, RIZOMUV_LUA_PATH)
from Modeling.UV.RizomBridge import RizomUVBridge
RizomUVBridge.run()
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running RizomUV Bridge: {e}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
# -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
# Rigging Functions
# ****************************************************************************************************************
def run_advanced_skeleton(self, *args):
try:
adv_sub_path = [
os.path.join(TOOL_PATH, 'Animation', 'AdvancedSkeleton').replace('\\', '/'),
os.path.join(TOOL_PATH, 'Animation', 'AdvancedSkeleton', 'AdvancedSkeleton5Files').replace('\\', '/')
]
for path in adv_sub_path:
if path not in sys.path:
sys.path.insert(0, path)
# If advancedSkeleton5Files does not exist, run the adv_install.py and the launch.py, else run the adv_launch.py directly
if not os.path.exists(os.path.join(TOOL_PATH, 'Animation', 'AdvancedSkeleton', 'adv_install.py').replace('\\', '/')):
from Animation.AdvancedSkeleton import adv_install
adv_install.install()
from Animation.AdvancedSkeleton import adv_launch
adv_launch.launch()
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running Advanced Skeleton: {e}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
print(f"Detailed error: {traceback.format_exc()}")
# -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
# Metahuman Functions
# ****************************************************************************************************************
# Preparation
def run_body_prepare(self, *args):
try:
BodyPrep.run()
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running Body Prepare: {e}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
# -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
# Animation Functions
# ****************************************************************************************************************
# Pose
def open_aTools(self, *args):
try:
# Get aTools path
ATOOLS_PATH = os.path.normpath(os.path.join(TOOL_PATH, 'Animation', 'aTools')).replace('\\', '/')
if ATOOLS_PATH not in sys.path:
sys.path.insert(0, ATOOLS_PATH)
ATOOLS_PARENT_PATH = os.path.dirname(ATOOLS_PATH)
if ATOOLS_PARENT_PATH not in sys.path:
sys.path.insert(0, ATOOLS_PARENT_PATH)
atools = importlib.import_module('aTools')
importlib.reload(atools)
animTools = importlib.import_module('aTools.animTools')
importlib.reload(animTools)
animBar = importlib.import_module('aTools.animTools.animBar')
importlib.reload(animBar)
animBarUI = importlib.import_module('aTools.animTools.animBar.animBarUI')
importlib.reload(animBarUI)
animBarUI.show('refresh')
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running aTools: {e}"
print(f"Detailed error: {traceback.format_exc()}")
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
def open_keyframe_pro(self, *args):
try:
KEYFRAME_PRO_PATH = [
os.path.join(TOOL_PATH, 'Animation', 'keyframe_pro'),
os.path.join(TOOL_PATH, 'Animation', 'keyframe_pro', 'keyframe_pro'),
os.path.join(TOOL_PATH, 'Animation', 'keyframe_pro', 'keyframe_pro_maya')
]
for path in KEYFRAME_PRO_PATH:
if path not in sys.path:
sys.path.insert(0, path)
for path in sys.path:
print("Added the keyframe_Pro submoudle path: ", path)
from Animation.keyframe_pro.keyframe_pro_maya.maya_to_keyframe_pro import MayaToKeyframePro
MayaToKeyframePro.display()
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running Keyframe Pro: {e}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
def run_dwpicker(self, *args):
try:
DWPICKER_PATH = os.path.normpath(os.path.join(TOOL_PATH, 'Animation', 'dwpicker')).replace('\\', '/')
if DWPICKER_PATH not in sys.path:
sys.path.insert(0, DWPICKER_PATH)
DWPICKER_SUB_PATHS = [
os.path.join(DWPICKER_PATH, 'scripts'),
os.path.join(DWPICKER_PATH, 'dwpicker')
]
for path in DWPICKER_SUB_PATHS:
if path not in sys.path:
sys.path.insert(0, path)
for path in sys.path:
print("Added the dwpicker submoudle path: ", path)
from Animation.dwpicker import dwpicker
dwpicker.show()
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running dwpicker: {e}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
def open_studio_library(self, *args):
try:
STUDIOLIBRARY_PATH = os.path.normpath(os.path.join(TOOL_PATH, 'Animation', 'studiolibrary')).replace('\\', '/')
STUDIOLIBRARY_SUB_PATHS = [
os.path.join(STUDIOLIBRARY_PATH, 'src'),
os.path.join(STUDIOLIBRARY_PATH, 'src', 'studiolibrary'),
os.path.join(STUDIOLIBRARY_PATH, 'src', 'studiolibrarymaya'),
os.path.join(STUDIOLIBRARY_PATH, 'src', 'studioqt'),
os.path.join(STUDIOLIBRARY_PATH, 'src', 'mutils'),
os.path.join(STUDIOLIBRARY_PATH, 'src', 'studiovendor')
]
# Added the main path to sys.path
if STUDIOLIBRARY_PATH not in sys.path:
sys.path.insert(0, STUDIOLIBRARY_PATH)
# Added the sub path to sys.path
for path in STUDIOLIBRARY_SUB_PATHS:
if path not in sys.path:
sys.path.insert(0, path.replace('\\', '/'))
for path in sys.path:
print("Added the studiolibrary submoudle path: ", path)
# Import studiolibrary from the STUDIOLIBRARY_PATH with importlib
studiolibrary = importlib.import_module('studiolibrary')
importlib.reload(studiolibrary)
# Run studiolibrary
studiolibrary.main()
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running Studio Library: {e}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
def run_anim_school_picker(self, *args):
try:
# Added the path to the AnimSchoolPicker.mel file
ANIMPICKER_PATH = os.path.normpath(os.path.join(TOOL_PATH, 'Animation', 'AnimSchoolPicker')).replace('\\', '/')
if ANIMPICKER_PATH not in sys.path:
sys.path.insert(0, ANIMPICKER_PATH)
# Get Maya Version
MAYA_VERSION = cmds.about(version=True).split()[0]
# Set plugin path
ANIMPICKER_PLUGIN_PATH = os.path.join(ANIMPICKER_PATH, MAYA_VERSION).replace('\\', '/')
# Added the plugin path to MAYA_PLUG_IN_PATH
os.environ['MAYA_PLUG_IN_PATH'] = ANIMPICKER_PLUGIN_PATH
# load the plugin
animpicker_mll = os.path.join(ANIMPICKER_PLUGIN_PATH, 'AnimSchoolPicker.mll').replace('\\', '/')
cmds.loadPlugin(animpicker_mll, quiet=True)
cmds.AnimSchoolPicker()
print(f"Anim School Picker loaded successfully from {animpicker_mll}")
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running Anim School Picker: {e}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
def run_bhghost(self, *args):
try:
bhghost_path = os.path.normpath(os.path.join(TOOL_PATH, 'Animation', 'bhGhost')).replace('\\', '/')
print(bhghost_path)
if bhghost_path not in sys.path:
sys.path.insert(0, bhghost_path)
bhghost_mel = os.path.join(bhghost_path, 'bhGhost.mel').replace('\\', '/')
print(bhghost_mel)
mel.eval(f'source "{bhghost_mel}";')
print(f"bhGhost loaded successfully from {bhghost_mel}")
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running bhGhost: {e}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
print(f"Detailed error: {traceback.format_exc()}")
def run_ik_fk_switch(self, *args):
try:
from Animation import mog_ikFkSwitchFree
mog_ikFkSwitchFree.FkIk_UI()
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running IK/FK Switch: {e}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
# Blendshape
def open_epic_pose_wrangler(self, *args):
try:
epic_pose_wrangler_path = os.path.join(TOOL_PATH, 'Animation', 'epic_pose_wrangler').replace('\\', '/')
sys.path.append(epic_pose_wrangler_path)
print(epic_pose_wrangler_path)
print(f"Attempting to import Epic Pose Wrangler from: {epic_pose_wrangler_path}")
MAYA_VERSION = cmds.about(version=True).split()[0]
plugin_dir = os.path.join(epic_pose_wrangler_path, 'plugins', 'Windows', MAYA_VERSION)
for plugin in ['embeddedRL4.mll', f'MayaUE4RBFPlugin{MAYA_VERSION}.mll', 'MayaUERBFPlugin.mll']:
plugin_path = os.path.join(plugin_dir, plugin)
if os.path.exists(plugin_path):
if not cmds.pluginInfo(plugin_path, query=True, loaded=True):
cmds.loadPlugin(plugin_path)
else:
print(f"Warning: Plugin file does not exist: {plugin_path}")
sys.path.insert(0, os.path.dirname(epic_pose_wrangler_path))
from Animation.epic_pose_wrangler import main
pose_wrangler = main.PoseWrangler()
cmds.inViewMessage(amg='Epic Pose Wrangler loaded successfully', pos='midCenter', fade=True)
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running Epic Pose Wrangler: {e}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
def run_universal_rig_adapter(self, *args):
try:
UniversalRigAdapter.run()
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running Universal Rig Adapter: {e}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
def run_morph_shape(self, *args):
try:
MorphShape.show()
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running MorphShape: {e}"
cmds.warning(ERROR_MESSAGE)
def run_icon_viewer(self, *args):
try:
from Dev.mayaiconview import create_icon_viewer
create_icon_viewer()
except Exception as e:
ERROR_MESSAGE = f"Error occurred while running Icon Viewer: {e}"
cmds.warning(ERROR_MESSAGE)
cmds.confirmDialog(title='Error', message=ERROR_MESSAGE, button=['OK'], defaultButton='OK')
def run_motioncap_helper(self, *args):
try:
plugin_folder = os.path.join(TOOL_PATH, 'Animation', 'MotionCapHelper', 'bin').replace('\\', '/')
if plugin_folder not in sys.path:
sys.path.append(plugin_folder)
os.environ['MAYA_PLUG_IN_PATH'] = os.pathsep.join([os.environ.get('MAYA_PLUG_IN_PATH', ''), plugin_folder])
plugin_path = os.path.join(plugin_folder, "mocaphelper.py").replace('\\', '/')
if not cmds.pluginInfo(plugin_path, query=True, loaded=True):
cmds.loadPlugin(plugin_path, quiet=True)
mel.eval("moCapHelper_showUi -lan \"CN\"")
except Exception as e:
self.show_error("MotionCap Helper", e)
def run_spring_magic(self, *args):
try:
from Animation.springmagic import main
main.main()
except Exception as e:
self.show_error("Spring Magic", e)
def run_ahoge(self, *args):
try:
ahoge_path = os.path.join(TOOL_PATH, 'Modeling', 'Edit','ahoge').replace('\\', '/')
maya_version = cmds.about(version=True).split()[0]
if maya_version not in ['2023', '2024', '2025']:
cmds.warning(u"Ahoge 目前只支持 Maya 2023, 2024, 2025 使用!")
return
plugin_dir = os.path.join(ahoge_path, 'plugins', maya_version)
paths = {
'MAYA_PLUG_IN_PATH': plugin_dir,
'MAYA_SCRIPT_PATH': os.path.join(ahoge_path, 'scripts'),
'XBMLANGPATH': os.path.join(ahoge_path, 'icons'),
'MTOA_EXTENSIONS_PATH': os.path.join(ahoge_path, 'mtoa')
}
for env_var, path in paths.items():
if os.path.exists(path):
current_path = os.environ.get(env_var, '')
if path not in current_path:
if current_path:
os.environ[env_var] = current_path + os.pathsep + path
else:
os.environ[env_var] = path
if env_var == 'MAYA_PLUG_IN_PATH':
mel.eval('putenv "MAYA_PLUG_IN_PATH" "' + os.environ['MAYA_PLUG_IN_PATH'] + '"')
plugin_path = os.path.join(plugin_dir, 'ahoge.mll').replace('\\', '/')
if not cmds.pluginInfo(plugin_path, query=True, loaded=True):
cmds.loadPlugin(plugin_path)
except Exception as e:
self.show_error("Ahoge", e)
def run_quad_remesher(self, *args):
try:
import Modeling.Edit.QuadRemesher.Contents.scripts.QuickInstall as qi
is_installed = qi.quick_install()
if is_installed == 1:
import QuadRemesher
QuadRemesher.QuadRemesher()
except Exception as e:
self.show_error("Quad Remesher", e)
def run_ldmt(self, *args):
try:
ldmt_path = os.path.join(TOOL_PATH, 'Modeling', 'Edit', 'LDMT').replace('\\', '/')
ldmt_func_path = os.path.join(ldmt_path, 'ldmt_function').replace('\\', '/')
for path in [ldmt_path, ldmt_func_path]:
if path not in sys.path:
sys.path.insert(0, path)
import ldmt_ui
ldmt_ui.show()
except Exception as e:
self.show_error("LDMT", e)
def run_simplify(self, *args):
try:
maya_version = cmds.about(version=True).split()[0]
# 判断版本对不对
if maya_version != "2018":
cmds.warning(u"Simplify 目前只支持 Maya 2018 使用!")
return
# 判断插件是否存在
simplify_path = "C:/Program Files/Autodesk/Maya2018/bin/plug-ins/eatechmeshtools.mll"
if not os.path.exists(simplify_path):
# 如果插件不存在则运行bat文件
bat_path = os.path.join(TOOL_PATH, 'Modeling', 'Edit', 'Simplify', 'LODTools_2018', 'set_EASimplify.bat').replace('\\', '/')
try:
subprocess.Popen([
'powershell.exe',
'Start-Process',
'"{}"'.format(bat_path),
'-Verb',
'RunAs'
])
cmds.confirmDialog(title='提示', message='Simplify 插件已安装成功,请重启 Maya', button=['OK'], defaultButton='OK')
except:
cmds.confirmDialog(title='提示', message='Simplify 安装失败!', button=['OK'], defaultButton='OK')
else:
if not cmds.pluginInfo(simplify_path, query=True, loaded=True):
cmds.loadPlugin(simplify_path)
mel.eval("EATechMeshTools_Simplify;")
except Exception as e:
self.show_error("Simplify", e)
# -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
# Help and Language
# ****************************************************************************************************************
def show_help(self):
# Specify the URL of the website you want to open
webbrowser.open(TOOL_HELP_URL)
def toggle_language(self):
global TOOL_LANG
TOOL_LANG = 'en_US' if TOOL_LANG == 'zh_CN' else 'zh_CN'
self.lang_btn.setText("EN" if TOOL_LANG == 'zh_CN' else "CN")
self.retranslate_ui()
QtWidgets.QToolTip.showText(
self.lang_btn.mapToGlobal(QtCore.QPoint(0, -30)),
"Language switched" if TOOL_LANG == 'en_US' else "语言已切换",
self.lang_btn
)
def retranslate_ui(self):
# Update all UI elements
self.setWindowTitle("MetaBox")
self.modeling_tab_btn.setText(LANG[TOOL_LANG]["Modeling"])
self.metahuman_tab_btn.setText(LANG[TOOL_LANG]["Metahuman"])
self.rigging_tab_btn.setText(LANG[TOOL_LANG]["Rigging"])
self.animation_tab_btn.setText(LANG[TOOL_LANG]["Animation"])
self.modeling_display_group.setTitle(LANG[TOOL_LANG]["Display"] )
self.modeling_xray_btn.setText(LANG[TOOL_LANG]["Xray"])
self.modeling_joint_xray_btn.setText(LANG[TOOL_LANG]["Joint Xray"])
self.modeling_manage_group.setTitle(LANG[TOOL_LANG]["Manage"])
self.modeling_rename_btn.setText(LANG[TOOL_LANG]["Rename"])
self.modeling_batch_import_btn.setText(LANG[TOOL_LANG]["Batch Import"])
self.modeling_select_group.setTitle(LANG[TOOL_LANG]["Select"])
self.modeling_interval_select_edge_btn.setText(LANG[TOOL_LANG]["Interval Select Edge"])
self.modeling_same_position_selector_btn.setText(LANG[TOOL_LANG]["Same Position Selector"])
self.modeling_edge_loop_smart_select_btn.setText(LANG[TOOL_LANG]["Edge Loop Smart Select"])
self.modeling_even_edge_loop_btn.setText(LANG[TOOL_LANG]["Even Edge Loop"])
self.modeling_tools_group.setTitle(LANG[TOOL_LANG]["Tools"])
self.modeling_crease_plus_btn.setText(LANG[TOOL_LANG]["Crease Plus"])
self.modeling_speed_cut_btn.setText(LANG[TOOL_LANG]["Speed Cut"])
self.modeling_modit_btn.setText(LANG[TOOL_LANG]["ModIt"])
self.modeling_plugit_btn.setText(LANG[TOOL_LANG]["PlugIt"])
self.modeling_zirail_btn.setText(LANG[TOOL_LANG]["Zirail"])
self.modeling_xgtools_btn.setText(LANG[TOOL_LANG]["Groomer`s Tool"])
self.modeling_edge_sensei_btn.setText(LANG[TOOL_LANG]["Edge Sensei"])
self.modeling_round_inset_btn.setText(LANG[TOOL_LANG]["Round Inset"])
self.modeling_arc_deformer_btn.setText(LANG[TOOL_LANG]["Arc Deformer"])
self.modeling_instant_drag_btn.setText(LANG[TOOL_LANG]["Instant Drag"])
self.modeling_unbevel_btn.setText(LANG[TOOL_LANG]["Un Bevel"])
self.modeling_align_edge_btn.setText(LANG[TOOL_LANG]["Align Edge"])
self.modeling_extra_curve_btn.setText(LANG[TOOL_LANG]["Extra Curve"])
self.modeling_auto_snap_btn.setText(LANG[TOOL_LANG]["Auto Snap"])
self.modeling_xgen_controller_btn.setText(LANG[TOOL_LANG]["Xgen Controller"])
self.modeling_speed_bend_btn.setText(LANG[TOOL_LANG]["Speed Bend"])
self.modeling_gs_curve_tools_group.setTitle(LANG[TOOL_LANG]["GS Curve Tools"])
self.modeling_gs_curve_tools_btn.setText(LANG[TOOL_LANG]["GS Curve Tools"])
self.modeling_reset_gs_curve_tools_btn.setText(LANG[TOOL_LANG]["GS Curve Tools Reset"])
self.modeling_close_gs_curve_tools_btn.setText(LANG[TOOL_LANG]["GS Curve Tools Close"])
self.modeling_uv_group.setTitle(LANG[TOOL_LANG]["UV"])
self.modeling_uvdeluxe_btn.setText(LANG[TOOL_LANG]["UVDeluxe"])
self.modeling_rizom_uv_bridge_btn.setText(LANG[TOOL_LANG]["RizomUV Bridge"])
self.modeling_uv_set_editor_btn.setText(LANG[TOOL_LANG]["UV Set Editor"])
self.metahuman_preparation_group.setTitle(LANG[TOOL_LANG]["Preparation"])
self.metahuman_body_prepare_btn.setText(LANG[TOOL_LANG]["Body Prepare"])
self.metahuman_batch_import_btn.setText(LANG[TOOL_LANG]["Batch Import"])
self.rigging_setup_group.setTitle(LANG[TOOL_LANG]["Setup"])
self.rigging_advanced_skeleton_btn.setText(LANG[TOOL_LANG]["Advanced Skeleton"])
self.animation_select_group.setTitle(LANG[TOOL_LANG]["Select"])
self.animation_animschool_picker_btn.setText(LANG[TOOL_LANG]["Anim School Picker"])
self.animation_dwpicker_btn.setText(LANG[TOOL_LANG]["DWPicker"])
self.animation_tools_group.setTitle(LANG[TOOL_LANG]["Tools"])
self.animation_bhghost_btn.setText(LANG[TOOL_LANG]["bhGhost"])
self.animation_ikfk_switch_btn.setText(LANG[TOOL_LANG]["IK/FK Switch"])
self.animation_atools_btn.setText(LANG[TOOL_LANG]["aTools"])
self.animation_keyframepro_btn.setText(LANG[TOOL_LANG]["Keyframe Pro"])
self.animation_studiolibrary_btn.setText(LANG[TOOL_LANG]["Studio Library"])
self.animation_pose_group.setTitle(LANG[TOOL_LANG]["Pose Tools"])
self.animation_epic_pose_wrangler_btn.setText(LANG[TOOL_LANG]["Epic Pose Wrangler"])
self.animation_morph_shape_btn.setText(LANG[TOOL_LANG]["Morph Shape"])
self.animation_universal_rig_adapter_btn.setText(LANG[TOOL_LANG]["Universal Rig Adapter"])
self.dev_tools_group.setTitle(LANG[TOOL_LANG]["Dev Tool"])
self.dev_icon_viewer_btn.setText(LANG[TOOL_LANG]["Icon Viewer"])
self.metahuman_import_group.setTitle(LANG[TOOL_LANG]["Import"])
self.animation_motioncap_helper_btn.setText(LANG[TOOL_LANG]["MotionCapHelper"])
self.animation_spring_magic_btn.setText(LANG[TOOL_LANG]["SpringMagic"])
self.modeling_ahoge_btn.setText(LANG[TOOL_LANG]["Ahoge"])
self.modeling_quad_remesher_btn.setText(LANG[TOOL_LANG]["QuadRemesher"])
self.modeling_ldmt_btn.setText(LANG[TOOL_LANG]["LDMT"])
self.modeling_simplify_btn.setText(LANG[TOOL_LANG]["Simplify"])
self.help_btn.setText(LANG[TOOL_LANG]["DOCUMENT"])
self.lang_btn.setText(LANG[TOOL_LANG]["CN" if TOOL_LANG == 'en_US' else "EN"])
self.lang_btn.setToolTip(LANG[TOOL_LANG]["Switch Language"])
for buttons_01 in [
self.help_btn,
self.lang_btn
]:
buttons_01.setFont(QtGui.QFont("Microsoft YaHei", 10))
for buttons_02 in [
# Modeling Group
self.modeling_tab_btn,
self.modeling_display_group,
self.modeling_select_group,
self.modeling_tools_group,
self.modeling_xray_btn,
self.modeling_joint_xray_btn,
self.modeling_rename_btn,
self.modeling_manage_group,
self.modeling_batch_import_btn,
self.modeling_ahoge_btn,
self.modeling_quad_remesher_btn,
self.modeling_ldmt_btn,
self.modeling_simplify_btn,
# Metahuman Group
self.metahuman_tab_btn,
self.metahuman_preparation_group,
self.metahuman_import_group,
self.metahuman_body_prepare_btn,
self.metahuman_batch_import_btn,
# Rigging Group
self.rigging_tab_btn,
self.rigging_setup_group,
self.rigging_advanced_skeleton_btn,
# Animation Group
self.animation_tab_btn,
self.animation_select_group,
self.animation_tools_group,
self.animation_pose_group,
self.animation_animschool_picker_btn,
self.animation_dwpicker_btn,
self.animation_bhghost_btn,
self.animation_ikfk_switch_btn,
self.animation_atools_btn,
self.animation_keyframepro_btn,
self.animation_studiolibrary_btn,
self.animation_epic_pose_wrangler_btn,
self.animation_morph_shape_btn,
self.animation_universal_rig_adapter_btn,
self.animation_motioncap_helper_btn,
self.animation_spring_magic_btn,
# Dev Tools Group
self.dev_tools_group,
self.dev_icon_viewer_btn
]:
buttons_02.setFont(QtGui.QFont("Microsoft YaHei", 8))
# -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
# Show Window
# ************************************************************************************************************************************************************************************************************
def show():
global main_window # Ensure this is the instance variable
current_width = 300
try:
if cmds.workspaceControl(TOOL_WSCL_NAME, exists=True):
current_width = cmds.workspaceControl(TOOL_WSCL_NAME, q=True, width=True)
cmds.deleteUI(TOOL_WSCL_NAME, control=True)
# Check if main_window is already defined and close it
if 'main_window' in globals() and main_window is not None:
main_window.close()
main_window.deleteLater()
except Exception as e:
print(f"Error during workspace control check: {str(e)}")
def create_ui(retry_count=0, width=300):
global main_window
try:
main_window = MainWindow() # Create an instance of MainWindow
main_window.dock_to_maya()
cmds.evalDeferred(lambda: cmds.workspaceControl(TOOL_WSCL_NAME, e=True, width=width, resizeWidth=True))
except Exception as e:
if retry_count < 3:
print(f"MetaBox creation failed, retrying... (Attempt {retry_count + 1})")
utils.executeDeferred(lambda: create_ui(retry_count + 1, width))
else:
print(f"Failed to create MetaBox after 3 attempts: {str(e)}")
utils.executeDeferred(lambda: create_ui(width=current_width))
if __name__ == "__main__":
show()