Files
NexusLauncher/docs/CUSTOM_PLUGIN_GUIDE.md
2025-11-23 21:03:42 +08:00

15 KiB
Raw Blame History

Maya 自定义插件添加指南

本指南将帮助你在 NexusLauncher 的 Maya 插件系统中添加自己的工具和插件。


📁 目录结构说明

template_plugins/maya/2023/
├── shelves/              # 工具架文件(.mel 格式)
├── scripts/              # Python/MEL 脚本
├── plug-ins/             # Maya 插件文件(.py 或 .mll
├── icons/                # 工具图标
└── README.md             # 基础说明文档

🎯 添加方式概览

根据你的需求,有三种主要的添加方式:

方式 适用场景 难度
1. 添加工具架按钮 快速添加 Python 脚本工具 简单
2. 添加 Maya 插件 创建 Maya 命令或节点 中等
3. 添加启动脚本 自动执行初始化代码 简单

方式 1: 添加工具架按钮

适用场景

  • 你有一个 Python 脚本工具想要快速访问
  • 需要在工具架上添加按钮
  • 不需要注册 Maya 命令

步骤

1.1 准备你的 Python 脚本

将你的 Python 脚本放到 scripts/ 目录:

scripts/
├── userSetup.py          # 启动脚本(已存在)
├── nexus_test.py         # 示例脚本(已存在)
└── my_custom_tool.py     # 👈 你的新脚本

示例脚本 (my_custom_tool.py):

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
我的自定义工具
"""
import maya.cmds as cmds

def run_my_tool():
    """执行我的工具"""
    # 你的工具逻辑
    cmds.confirmDialog(
        title='My Tool',
        message='Hello from my custom tool!',
        button=['OK']
    )
    print("[MyTool] Tool executed successfully")

def show_ui():
    """显示工具界面"""
    # 如果有 UI在这里创建
    pass

1.2 准备图标(可选)

将图标文件放到 icons/ 目录:

icons/
├── nexus_test.png        # 示例图标(已存在)
└── my_tool_icon.png      # 👈 你的图标32x32 或 64x64 PNG

提示: 如果没有图标,可以使用文字标签代替

1.3 编辑工具架文件

编辑 shelves/shelf_NexusLauncher.mel,在文件末尾的 } 之前添加新按钮:

    shelfButton
        -enableCommandRepeat 1
        -flexibleWidthType 3
        -flexibleWidthValue 32
        -enable 1
        -width 35
        -height 34
        -manage 1
        -visible 1
        -preventOverride 0
        -annotation "我的自定义工具 - 点击运行" 
        -enableBackground 0
        -backgroundColor 0 0 0 
        -highlightColor 0.321569 0.521569 0.65098 
        -align "center" 
        -label "MT" 
        -labelOffset 0
        -rotation 0
        -flipX 0
        -flipY 0
        -useAlpha 1
        -font "boldLabelFont" 
        -imageOverlayLabel "MT" 
        -overlayLabelColor 1 1 1 
        -overlayLabelBackColor 0.2 0.8 0.5 0.9 
        -image "my_tool_icon.png" 
        -image1 "my_tool_icon.png" 
        -style "iconOnly" 
        -marginWidth 0
        -marginHeight 1
        -command "import my_custom_tool\nmy_custom_tool.run_my_tool()" 
        -sourceType "python" 
        -commandRepeatable 1
        -flat 1
    ;

关键参数说明:

  • -annotation: 鼠标悬停时的提示文字
  • -label: 按钮文字标签(如果没有图标会显示)
  • -imageOverlayLabel: 图标上的文字叠加层
  • -overlayLabelBackColor: 文字背景颜色 (R G B Alpha)
  • -image: 图标文件名(在 icons/ 目录中)
  • -command: 点击按钮时执行的 Python 代码

1.4 测试

  1. 通过 NexusLauncher 启动 Maya 2023
  2. 检查 NexusLauncher 工具架是否出现新按钮
  3. 点击按钮测试功能

方式 2: 添加 Maya 插件

适用场景

  • 需要注册自定义 Maya 命令
  • 需要创建自定义节点
  • 需要更深度的 Maya API 集成

步骤

2.1 创建插件文件

plug-ins/ 目录创建你的插件文件:

plug-ins/
├── nexus_example_plugin.py    # 示例插件(已存在)
└── my_custom_plugin.py         # 👈 你的新插件

插件模板 (my_custom_plugin.py):

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
我的自定义 Maya 插件
"""
import sys
import maya.api.OpenMaya as om


def maya_useNewAPI():
    """告诉 Maya 使用 Python API 2.0"""
    pass


class MyCustomCommand(om.MPxCommand):
    """自定义命令类"""
    
    kPluginCmdName = 'myCustomCmd'  # 命令名称
    
    def __init__(self):
        om.MPxCommand.__init__(self)
    
    @staticmethod
    def cmdCreator():
        return MyCustomCommand()
    
    def doIt(self, args):
        """执行命令"""
        print(f'[MyPlugin] Custom command executed!')
        om.MGlobal.displayInfo('My custom plugin is working!')
        
        # 在这里添加你的命令逻辑
        # 例如:创建对象、修改场景等


def initializePlugin(plugin):
    """初始化插件"""
    pluginFn = om.MFnPlugin(plugin, 'YourName', '1.0', 'Any')
    try:
        pluginFn.registerCommand(
            MyCustomCommand.kPluginCmdName,
            MyCustomCommand.cmdCreator
        )
        print(f'[MyPlugin] Plugin loaded: {MyCustomCommand.kPluginCmdName}')
    except:
        sys.stderr.write(f'Failed to register command: {MyCustomCommand.kPluginCmdName}')
        raise


def uninitializePlugin(plugin):
    """卸载插件"""
    pluginFn = om.MFnPlugin(plugin)
    try:
        pluginFn.deregisterCommand(MyCustomCommand.kPluginCmdName)
        print(f'[MyPlugin] Plugin unloaded: {MyCustomCommand.kPluginCmdName}')
    except:
        sys.stderr.write(f'Failed to deregister command: {MyCustomCommand.kPluginCmdName}')
        raise

2.2 配置自动加载

编辑 scripts/userSetup.py,在 load_nexus_plugins() 函数中添加你的插件:

def load_nexus_plugins():
    """Load NexusLauncher plugins"""
    try:
        plugin_path = os.environ.get('MAYA_PLUG_IN_PATH', '')
        
        if not plugin_path:
            print("[NexusLauncher] MAYA_PLUG_IN_PATH not set, skipping plugin load")
            return
        
        print(f"[NexusLauncher] MAYA_PLUG_IN_PATH: {plugin_path}")
        
        # 要加载的插件列表
        plugins_to_load = [
            "nexus_example_plugin.py",
            "my_custom_plugin.py",  # 👈 添加你的插件
        ]
        
        for plugin_file in plugins_to_load:
            if cmds.pluginInfo(plugin_file, query=True, loaded=True):
                print(f"[NexusLauncher] Plugin already loaded: {plugin_file}")
            else:
                try:
                    cmds.loadPlugin(plugin_file)
                    print(f"[NexusLauncher] ✓ Loaded plugin: {plugin_file}")
                    
                    # 设置为自动加载
                    cmds.pluginInfo(plugin_file, edit=True, autoload=True)
                    print(f"[NexusLauncher] ✓ Set plugin to auto-load")
                except Exception as e:
                    print(f"[NexusLauncher] Failed to load plugin {plugin_file}: {e}")
    
    except Exception as e:
        print(f"[NexusLauncher] Error loading plugins: {e}")

2.3 测试插件

  1. 通过 NexusLauncher 启动 Maya 2023
  2. 检查脚本编辑器输出,确认插件已加载
  3. 在 Maya 命令行或脚本编辑器中测试命令:
import maya.cmds as cmds
cmds.myCustomCmd()  # 执行你的自定义命令

方式 3: 添加启动脚本

适用场景

  • 需要在 Maya 启动时自动执行某些操作
  • 设置环境变量或全局配置
  • 加载第三方库

步骤

3.1 编辑 userSetup.py

scripts/userSetup.py 文件末尾添加你的初始化代码:

def my_custom_startup():
    """我的自定义启动函数"""
    try:
        print("[MyStartup] Running custom startup code...")
        
        # 在这里添加你的启动逻辑
        # 例如:
        # - 设置默认渲染器
        # - 加载常用插件
        # - 配置工作区
        # - 连接到资产管理系统
        
        import maya.cmds as cmds
        
        # 示例:设置默认单位为厘米
        cmds.currentUnit(linear='cm')
        print("[MyStartup] ✓ Set default unit to cm")
        
        # 示例:设置默认时间单位为 24fps
        cmds.currentUnit(time='film')
        print("[MyStartup] ✓ Set default time unit to 24fps")
        
        print("[MyStartup] ✓ Custom startup completed")
        
    except Exception as e:
        print(f"[MyStartup] Error during startup: {e}")


# 在 Maya 启动完成后执行
cmds.evalDeferred(my_custom_startup)

🔧 高级技巧

1. 动态重载工具架

如果你在开发过程中频繁修改工具架,可以使用 RELOAD_SHELF.py 快速重载:

# 在 Maya 脚本编辑器中执行
import sys
sys.path.append(r'E:\Zoroot\Dev\NexusLauncher\template\plugins\maya\2023')
import RELOAD_SHELF
RELOAD_SHELF.reload_shelf()

2. 使用相对导入

如果你的工具有多个模块,可以创建包结构:

scripts/
├── my_tool/
│   ├── __init__.py
│   ├── core.py
│   ├── ui.py
│   └── utils.py
└── userSetup.py

在工具架按钮中使用:

-command "from my_tool import ui\nui.show_window()" 

3. 添加菜单项

除了工具架按钮,你还可以在 userSetup.py 中添加自定义菜单:

def create_custom_menu():
    """创建自定义菜单"""
    try:
        import maya.cmds as cmds
        
        # 检查菜单是否已存在
        if cmds.menu('NexusMenu', exists=True):
            cmds.deleteUI('NexusMenu')
        
        # 创建菜单
        main_window = mel.eval('$tmpVar=$gMainWindow')
        custom_menu = cmds.menu(
            'NexusMenu',
            label='NexusTools',
            parent=main_window,
            tearOff=True
        )
        
        # 添加菜单项
        cmds.menuItem(
            label='My Tool',
            command='import my_custom_tool; my_custom_tool.run_my_tool()',
            parent=custom_menu
        )
        
        cmds.menuItem(divider=True, parent=custom_menu)
        
        cmds.menuItem(
            label='About',
            command='cmds.confirmDialog(title="About", message="NexusTools v1.0")',
            parent=custom_menu
        )
        
        print("[NexusLauncher] ✓ Created custom menu")
        
    except Exception as e:
        print(f"[NexusLauncher] Error creating menu: {e}")

# 在启动时执行
cmds.evalDeferred(create_custom_menu)

4. 调试技巧

查看环境变量:

import os
print(os.environ.get('MAYA_SHELF_PATH'))
print(os.environ.get('MAYA_PLUG_IN_PATH'))

检查插件加载状态:

import maya.cmds as cmds
print(cmds.pluginInfo(query=True, listPlugins=True))

查看工具架列表:

import maya.cmds as cmds
print(cmds.lsUI(type='shelfLayout'))

📋 常见问题

Q1: 工具架按钮不显示图标?

A: 检查以下几点:

  1. 图标文件是否在 icons/ 目录中
  2. 文件名是否正确(区分大小写)
  3. 图标格式是否为 PNG
  4. XBMLANGPATH 环境变量是否正确设置

Q2: Python 脚本找不到模块?

A: 确保:

  1. 脚本在 scripts/ 目录中
  2. PYTHONPATHMAYA_SCRIPT_PATH 已正确设置
  3. 使用 import 时不需要包含 .py 后缀

Q3: 插件加载失败?

A: 检查:

  1. 插件文件语法是否正确
  2. 是否包含 maya_useNewAPI() 函数API 2.0
  3. initializePlugin()uninitializePlugin() 是否正确实现
  4. 查看脚本编辑器的错误信息

Q4: 修改后没有生效?

A: 尝试:

  1. 完全关闭 Maya 重新启动
  2. 使用 RELOAD_SHELF.py 重载工具架
  3. 检查是否修改了正确版本的文件2023/2025

Q5: 工具架在非 NexusLauncher 启动时也出现?

A: 这是正常的,因为 Maya 会保存工具架配置。解决方法:

  • 系统已配置为临时工具架,不会保存到配置文件
  • 如果仍然出现,删除 Documents\maya\2023\prefs\shelves\shelf_NexusLauncher.mel

🎓 学习资源

Maya Python API

MEL 脚本


📝 最佳实践

  1. 命名规范

    • 使用有意义的名称
    • 避免与 Maya 内置命令冲突
    • 使用前缀区分自己的工具(如 nexus_, my_
  2. 错误处理

    • 始终使用 try-except 包裹关键代码
    • 提供清晰的错误信息
    • 使用 print() 输出调试信息
  3. 代码组织

    • 将复杂工具拆分为多个模块
    • 使用函数和类组织代码
    • 添加文档字符串说明
  4. 性能优化

    • 避免在启动时执行耗时操作
    • 使用 cmds.evalDeferred() 延迟执行
    • 只加载必要的插件
  5. 版本兼容

    • 如果支持多个 Maya 版本,注意 API 差异
    • 2023/2025/ 目录分别维护
    • 测试不同版本的兼容性

🚀 快速开始示例

完整示例:添加一个"创建立方体"工具

1. 创建脚本 (scripts/create_cube_tool.py):

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
创建立方体工具
"""
import maya.cmds as cmds

def create_custom_cube():
    """创建一个自定义立方体"""
    # 创建立方体
    cube = cmds.polyCube(name='CustomCube', width=2, height=2, depth=2)[0]
    
    # 设置颜色
    cmds.polyColorPerVertex(cube, rgb=(1, 0.5, 0), colorDisplayOption=True)
    
    # 移动到原点上方
    cmds.move(0, 1, 0, cube)
    
    print(f"[CreateCube] Created cube: {cube}")
    cmds.select(cube)
    
    return cube

2. 添加工具架按钮 (编辑 shelves/shelf_NexusLauncher.mel):

    shelfButton
        -annotation "Create Custom Cube" 
        -label "Cube" 
        -imageOverlayLabel "CB" 
        -overlayLabelBackColor 0.8 0.5 0.2 0.9 
        -command "import create_cube_tool\ncreate_cube_tool.create_custom_cube()" 
        -sourceType "python" 
    ;

3. 测试

  • 启动 Maya
  • 点击工具架上的 "CB" 按钮
  • 应该会创建一个橙色的立方体

📞 获取帮助

如果遇到问题:

  1. 检查 Maya 脚本编辑器的错误信息
  2. 查看本指南的"常见问题"部分
  3. 参考示例插件代码
  4. 查阅 Maya 官方文档

祝你开发愉快! 🎉