diff --git a/2023/scripts/animation_tools/SHELF_BUTTONS.md b/2023/scripts/animation_tools/SHELF_BUTTONS.md deleted file mode 100644 index f644826..0000000 --- a/2023/scripts/animation_tools/SHELF_BUTTONS.md +++ /dev/null @@ -1,321 +0,0 @@ -# Maya 工具架按钮命令 - -所有工具的标准启动命令,**不需要使用绝对路径**。 - -## 📋 前提条件 - -确保 `animation_tools` 在 Maya 的 Python 路径中。通常通过以下方式之一: - -1. **userSetup.py** (推荐) - ```python - import sys - import os - scripts_path = r'h:\Workspace\Raw\Tools\Plugins\Maya\2023\scripts' - if scripts_path not in sys.path: - sys.path.insert(0, scripts_path) - ``` - -2. **Maya.env** - ``` - PYTHONPATH=h:\Workspace\Raw\Tools\Plugins\Maya\2023\scripts - ``` - -## 🔧 工具架按钮命令 - -### 1. Studio Library - -**Python 命令:** -```python -import animation_tools.studiolibrary as studiolib -studiolib.show() -``` - -**MEL 命令:** -```mel -python("import animation_tools.studiolibrary as studiolib; studiolib.show()"); -``` - ---- - -### 2. DreamWall Picker - -**Python 命令:** -```python -import animation_tools.dwpicker as dwpicker -dwpicker.show() -``` - -**MEL 命令:** -```mel -python("import animation_tools.dwpicker as dwpicker; dwpicker.show()"); -``` - -**切换显示/隐藏:** -```python -import animation_tools.dwpicker as dwpicker -dwpicker.toggle() -``` - ---- - -### 3. MG-Picker Studio - -**Python 命令(Animator 模式):** -```python -import animation_tools.mgpicker as mgpicker -mgpicker.start() -``` - -**Python 命令(Designer 模式):** -```python -import animation_tools.mgpicker as mgpicker -mgpicker.start(mode=0) -``` - -**MEL 命令:** -```mel -python("import animation_tools.mgpicker as mgpicker; mgpicker.start()"); -``` - ---- - -### 4. IK/FK Switcher - -**Python 命令:** -```python -import animation_tools.ik_fk_switcher as ikfk -ikfk.show() -``` - -**MEL 命令:** -```mel -python("import animation_tools.ik_fk_switcher as ikfk; ikfk.show()"); -``` - ---- - -## 📝 创建工具架按钮步骤 - -### 方法 1:通过 Maya UI - -1. 打开 **Script Editor**(脚本编辑器) -2. 在 **Python** 标签页输入命令 -3. 选中代码 -4. **鼠标中键拖拽** 到工具架 -5. 右键点击按钮 → **Edit** → 设置图标和标签 - -### 方法 2:通过 MEL 命令 - -```mel -// Studio Library -shelfButton - -command "python(\"import animation_tools.studiolibrary as studiolib; studiolib.show()\")" - -annotation "Studio Library" - -label "StudioLib" - -image "commandButton.png" - -imageOverlayLabel "SL"; - -// DreamWall Picker -shelfButton - -command "python(\"import animation_tools.dwpicker as dwpicker; dwpicker.show()\")" - -annotation "DreamWall Picker" - -label "DWPicker" - -image "commandButton.png" - -imageOverlayLabel "DW"; - -// MG-Picker -shelfButton - -command "python(\"import animation_tools.mgpicker as mgpicker; mgpicker.start()\")" - -annotation "MG-Picker Studio" - -label "MGPicker" - -image "commandButton.png" - -imageOverlayLabel "MG"; - -// IK/FK Switcher -shelfButton - -command "python(\"import animation_tools.ik_fk_switcher as ikfk; ikfk.show()\")" - -annotation "IK/FK Switcher" - -label "IK/FK" - -image "commandButton.png" - -imageOverlayLabel "IK"; -``` - ---- - -## 🎨 推荐的按钮图标 - -### Studio Library -- **图标**: `UVEditorSnapshot.png` 或 `folder-open.png` -- **标签**: `SL` 或 `Studio` - -### DreamWall Picker -- **图标**: `pickHandlesComp.png` 或 `pickOtherComp.png` -- **标签**: `DW` 或 `Picker` - -### MG-Picker -- **图标**: `pickWalkUp.png` 或 `selectByHierarchy.png` -- **标签**: `MG` 或 `MGPick` - -### IK/FK Switcher -- **图标**: `ikSCsolver.png` 或 `kinHandle.png` -- **标签**: `IK` 或 `Switch` - ---- - -## ⚠️ 常见问题 - -### 问题 1: ModuleNotFoundError: No module named 'animation_tools' - -**原因**: `animation_tools` 不在 Python 路径中 - -**解决方案**: -1. 检查 `userSetup.py` 是否正确设置 -2. 或在按钮命令前添加路径: - ```python - import sys - scripts_path = r'h:\Workspace\Raw\Tools\Plugins\Maya\2023\scripts' - if scripts_path not in sys.path: - sys.path.insert(0, scripts_path) - - import animation_tools.studiolibrary as studiolib - studiolib.show() - ``` - -### 问题 2: 工具重复打开 - -**原因**: 没有使用正确的启动命令 - -**解决方案**: 使用本文档中的标准命令,所有工具都有窗口管理机制 - -### 问题 3: 版本不兼容 - -**原因**: 使用了错误的 Maya 版本目录 - -**解决方案**: -- Maya 2023 使用: `Maya\2023\scripts` -- Maya 2024 使用: `Maya\2024\scripts` -- Maya 2025 使用: `Maya\2025\scripts` - ---- - -## 📦 完整的 userSetup.py 示例 - -创建或编辑: `Documents/maya/scripts/userSetup.py` - -```python -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -""" -Maya User Setup -自动加载动画工具路径 -""" - -import sys -import os -import maya.cmds as cmds - -def setup_animation_tools(): - """设置动画工具路径""" - # 获取 Maya 版本 - maya_version = cmds.about(version=True).split('.')[0] - - # 构建路径 - base_path = r'h:\Workspace\Raw\Tools\Plugins\Maya' - scripts_path = os.path.join(base_path, maya_version, 'scripts') - - # 添加到 Python 路径 - if os.path.exists(scripts_path): - if scripts_path not in sys.path: - sys.path.insert(0, scripts_path) - print("Animation tools loaded from: " + scripts_path) - else: - print("Warning: Animation tools path not found: " + scripts_path) - -# 在 Maya 启动时执行 -if __name__ == '__main__': - cmds.evalDeferred(setup_animation_tools) -``` - ---- - -## ✅ 验证安装 - -在 Maya Script Editor 中运行: - -```python -import sys -print("Python paths:") -for path in sys.path[:5]: - print(" -", path) - -print("\nTesting imports:") -try: - import animation_tools.studiolibrary - print(" ✓ Studio Library") -except ImportError as e: - print(" ✗ Studio Library:", e) - -try: - import animation_tools.dwpicker - print(" ✓ DreamWall Picker") -except ImportError as e: - print(" ✗ DreamWall Picker:", e) - -try: - import animation_tools.mgpicker - print(" ✓ MG-Picker") -except ImportError as e: - print(" ✗ MG-Picker:", e) - -try: - import animation_tools.ik_fk_switcher - print(" ✓ IK/FK Switcher") -except ImportError as e: - print(" ✗ IK/FK Switcher:", e) -``` - -预期输出: -``` -Python paths: - - h:\Workspace\Raw\Tools\Plugins\Maya\2023\scripts - - ... - -Testing imports: - ✓ Studio Library - ✓ DreamWall Picker - ✓ MG-Picker - ✓ IK/FK Switcher -``` - ---- - -## 🚀 快速启动所有工具 - -```python -# 一键启动所有动画工具 -import animation_tools.studiolibrary as studiolib -import animation_tools.dwpicker as dwpicker -import animation_tools.mgpicker as mgpicker -import animation_tools.ik_fk_switcher as ikfk - -studiolib.show() -dwpicker.show() -mgpicker.start() -ikfk.show() -``` - ---- - -## 📞 支持 - -如果遇到问题: - -1. 检查 Python 路径是否正确 -2. 检查 Maya 版本是否匹配 -3. 查看 Script Editor 的完整错误信息 -4. 确认所有文件都在正确的位置 - ---- - -**所有工具现在都支持无绝对路径启动!** ✨ diff --git a/2023/scripts/animation_tools/ik_fk_switcher.py b/2023/scripts/animation_tools/ik_fk_switcher.py index 9fb5b34..2598c7b 100644 --- a/2023/scripts/animation_tools/ik_fk_switcher.py +++ b/2023/scripts/animation_tools/ik_fk_switcher.py @@ -14,7 +14,7 @@ import maya.cmds as cmds import maya.mel as mel import maya.OpenMaya as om #from math import isclose -# from sys import exit # 已移除,避免 SystemExit 错误 +# from sys import exit # Removed to avoid SystemExit error ################################################################################################################################################################################################################## @@ -71,8 +71,10 @@ def documentation(): def assist_message(message, time, to_exit=True): # ---------- DONE #POPS UP A MESSAGE ON THE USER'S SCREEN TO INFORM THEM OF SOMETHING cmds.inViewMessage(amg="" + message + "", pos='midCenter', fade=True, fst=time, ck=True) + # Also display warning in Script Editor + cmds.warning(message) if to_exit: - return # 不使用 exit(),避免 SystemExit 错误 + return # Do not use exit() to avoid SystemExit error def get_constraint_attribute(constraint_type): #SETS A KEY ON THE START AND END OF THE TIMELINE, SO THAT WE ENSURE THERE'S A BLEND NODE ALL THE TIME. IF THERE'S NO KEY BEFORE ADDING THE SETUP, THE SCRIPT WON'T APPLY A SWITCH ON THE BLEND NODE @@ -736,9 +738,9 @@ def delete_setup(): try: _delete_setup_impl() except Exception as e: - # 捕获所有错误,避免 SystemExit + # Catch all errors to avoid SystemExit if "SystemExit" not in str(type(e)): - cmds.warning("Delete setup failed: " + str(e)) # ✓ 使用字符串拼接 + cmds.warning("Delete setup failed: " + str(e)) # Using string concatenation for Python 2.7 compatibility def _delete_setup_impl(): clear_keys = cmds.checkBoxGrp("remove_unnecessary_keys", q=True, v1=True) @@ -851,7 +853,7 @@ import maya.cmds as cmds import maya.mel as mel import maya.OpenMaya as om -# from sys import exit # 已移除,避免 SystemExit 错误 +# from sys import exit # Removed to avoid SystemExit error bake_interval = """ + str(cmds.intFieldGrp("BakeInterval_IntField", q=True, v1=True)) + """ apply_key_reducer = """ + str(cmds.checkBoxGrp("ApplyKeyReducer_CheckBox", q=True, v1=True)) + """ @@ -912,9 +914,10 @@ def set_form_layout_coordinates(form_layout, name, top_coordinates, left_coordin def assist_message(message, time, to_exit=True): # ---------- DONE #POPS UP A MESSAGE ON THE USER'S SCREEN TO INFORM THEM OF SOMETHING cmds.inViewMessage(amg="" + message + "", pos='midCenter', fade=True, fst=time, ck=True) - # 不再使用 exit(),因为它会在 Maya 中产生 SystemExit 错误 - # 调用者应该检查返回值并决定是否继续执行 - return not to_exit # 返回 False 表示应该停止,True 表示可以继续 + # Also display warning in Script Editor + cmds.warning(message) + if to_exit: + return # Do not use exit() to avoid SystemExit error def get_constraint_attribute(constraint_type): #SETS A KEY ON THE START AND END OF THE TIMELINE, SO THAT WE ENSURE THERE'S A BLEND NODE ALL THE TIME. IF THERE'S NO KEY BEFORE ADDING THE SETUP, THE SCRIPT WON'T APPLY A SWITCH ON THE BLEND NODE @@ -1127,6 +1130,7 @@ def get_original_fk_controls(): # ---------- DONE fk_ctrls = cmds.ls(sl=True) if len(fk_ctrls) != 3: assist_message("Incorrect number of controls selected. To apply an IK setup, you need to select 3 FK controls, in order of parent to child.", 4000) + return None cmds.select(cl=True) return fk_ctrls @@ -1338,6 +1342,7 @@ def get_original_ik_controls(): ik_ctrls = cmds.ls(sl=True) if len(ik_ctrls) != 2: assist_message("Incorrect number of controls selected. To apply an FK setup, you need to select the Pole Vector first and then the IK Control, in order.", 4000) + return None cmds.select(cl=True) return ik_ctrls @@ -1668,7 +1673,7 @@ def extraOptions(): cmds.showWindow("Extra_Options") -# 导出主要函数,使其可以从外部调用 +# Export main functions for external use __all__ = [ 'fk_to_ik', 'ik_to_fk', @@ -1676,14 +1681,15 @@ __all__ = [ 'documentation', 'extraOptions', 'user_interface', + 'show', ] def show(): """ - 便捷函数:启动 IK/FK Switcher UI + Convenience function: Launch IK/FK Switcher UI - 使用方法: + Usage: import animation_tools.ik_fk_switcher as ikfk ikfk.show() """ diff --git a/2023/scripts/animation_tools/studiolibrary/__init__.py b/2023/scripts/animation_tools/studiolibrary/__init__.py index fcef2d3..a1004f1 100644 --- a/2023/scripts/animation_tools/studiolibrary/__init__.py +++ b/2023/scripts/animation_tools/studiolibrary/__init__.py @@ -3,10 +3,10 @@ """ Studio Library Wrapper Module -用于简化 Studio Library 的导入和使用 -支持 Maya 2017-2026+ 所有版本 +Simplify Studio Library import and usage +Support Maya 2017-2026+ all versions -使用方法: +Usage: import animation_tools.studiolibrary animation_tools.studiolibrary.show() """ @@ -14,36 +14,53 @@ Studio Library Wrapper Module import sys import os -# 获取当前目录 +# Get current directory _current_dir = os.path.dirname(os.path.abspath(__file__)) -# 全局变量用于存储导入的模块 +# Global variable to store imported module _studiolibrary_module = None __version__ = "2.20.2" def _ensure_studiolibrary_loaded(): - """确保 studiolibrary 模块已加载""" + """Ensure studiolibrary module is loaded""" global _studiolibrary_module if _studiolibrary_module is not None: return _studiolibrary_module - # 添加所有必要的路径 + # Add all necessary paths _inner_studiolibrary = os.path.join(_current_dir, 'studiolibrary') - for _subdir in ['studiolibrary', 'studiolibrarymaya', 'mutils', 'studioqt', 'studiovendor']: + for _subdir in ['studiolibrarymaya', 'mutils', 'studioqt', 'studiovendor']: _subdir_path = os.path.join(_current_dir, _subdir) if _subdir_path not in sys.path: sys.path.insert(0, _subdir_path) - # 导入 studiolibrary - import studiolibrary - _studiolibrary_module = studiolibrary + # Import from inner studiolibrary by temporarily manipulating sys.path + # Remove current directory to avoid circular import + _saved_path = sys.path[:] + if _current_dir in sys.path: + sys.path.remove(_current_dir) + + # Add inner studiolibrary to the front + if _inner_studiolibrary not in sys.path: + sys.path.insert(0, _inner_studiolibrary) + + try: + import studiolibrary + _studiolibrary_module = studiolibrary + finally: + # Restore sys.path + sys.path = _saved_path + # But keep the inner studiolibrary path + if _inner_studiolibrary not in sys.path: + sys.path.insert(0, _inner_studiolibrary) + return _studiolibrary_module def version(): return __version__ -# 导出所有公共接口 +# Export all public interfaces __all__ = [ '__version__', 'version', @@ -54,14 +71,14 @@ __all__ = [ def show(*args, **kwargs): """ - 便捷函数:启动 Studio Library + Convenience function: Launch Studio Library Args: - *args: 传递给 main() 的位置参数 - **kwargs: 传递给 main() 的关键字参数 + *args: Positional arguments passed to main() + **kwargs: Keyword arguments passed to main() Returns: - LibraryWindow: Studio Library 窗口实例 + LibraryWindow: Studio Library window instance Example: >>> import animation_tools.studiolibrary @@ -72,14 +89,14 @@ def show(*args, **kwargs): def main(*args, **kwargs): """ - 启动 Studio Library 主窗口 + Launch Studio Library main window Args: - *args: 传递给 main() 的位置参数 - **kwargs: 传递给 main() 的关键字参数 + *args: Positional arguments passed to main() + **kwargs: Keyword arguments passed to main() Returns: - LibraryWindow: Studio Library 窗口实例 + LibraryWindow: Studio Library window instance """ lib = _ensure_studiolibrary_loaded() return lib.main(*args, **kwargs) @@ -87,10 +104,10 @@ def main(*args, **kwargs): def isMaya(): """ - 检查是否在 Maya 环境中运行 + Check if running in Maya environment Returns: - bool: 如果在 Maya 中返回 True,否则返回 False + bool: True if in Maya, False otherwise """ try: import maya.cmds diff --git a/2023/shelves/shelf_Nexus_Animation.mel b/2023/shelves/shelf_Nexus_Animation.mel index 08480b7..f411c90 100644 --- a/2023/shelves/shelf_Nexus_Animation.mel +++ b/2023/shelves/shelf_Nexus_Animation.mel @@ -174,7 +174,7 @@ global proc shelf_Nexus_Animation () { -style "iconOnly" -marginWidth 0 -marginHeight 1 - -command "import sys\nimport os\nstudiolibrary_path = r'h:\\Workspace\\Raw\\Tools\\Plugins\\Maya\\2023\\scripts\\animation_tools\\studiolibrary'\nif studiolibrary_path not in sys.path:\n sys.path.insert(0, studiolibrary_path)\nimport studiolibrary\nstudiolibrary.main()" + -command "import animation_tools.studiolibrary as studiolib\nstudiolib.show()" -sourceType "python" -commandRepeatable 1 -flat 1