如何在Maya MEL中安全地向现有菜单添加菜单项。

4

我尝试使用MEL向Maya中的现有菜单添加菜单项。

示例:

menuItem -label "Mylabel" -insertAfter "someEntry" -parent $gMainFileMenu;
menuItem -label "Mylabel2" -insertAfter "someEntry" -parent $gMainFileMenu;

问题在于菜单并没有像应该那样由正常的条目填充,而只有我用这两行代码添加的条目。
例如,文件菜单通常包含“新建场景”,“打开场景”,“保存场景”等内容,但是当我使用这两行代码时,它只包含“Mylabel”和“Mylabel2”。
是否有解决方法或解决方法来确保菜单被完全填充?是否有一种方法强制Maya构建它,而不需要用户实际上点击它?
1个回答

8
实际问题在于Maya在用户第一次打开菜单时首先填充菜单。它会检查菜单长度是否大于0,如果是,则不填充。因为你已经添加了2个条目,所以菜单长度大于0,就不会用标准条目填充了。
要解决这个问题,有两种方法。你可以通过强制构建菜单项或注册构建menuItem来完成。两种方法都适用于不同的情况。
通过强制构建菜单:
你需要做的是找到Maya调用构建菜单的函数。你可以在文件夹/scripts/startup/*中找到这些函数。一个好的方法是打开Maya控制台,启用“echo all commands”,然后单击要查看构建函数的菜单。
在你的情况下,函数名为buildFileMenu(),可以在脚本FileMenu.mel中找到。
现在你有了这个函数名称,你需要检查它的参数。有时它需要一个菜单名称作为参数,有时不需要。关于如何找到菜单名称,请参见底部部分。
现在让我们开始构建它。
global string $gMainFileMenu; // Retrieve the menu name
buildFileMenu(); //  Build it

// Now build your menu
menuItem -divider true -parent $gMainFileMenu SuperMenuDivider;
menuItem -label "MyLabel1" -parent $gMainFileMenu SuperMenuLab1;
menuItem -label "MyLabel2" -parent $gMainFileMenu SuperMenuLab2;

// Create a proc to remove your menu items
global proc RemoveMyMenuItems()
{
    if(`menuItem -ex SuperMenuDivider`) deleteUI -mi SuperMenuDivider;
    if(`menuItem -ex SuperMenuLab1`) deleteUI -mi SuperMenuLab1;
    if(`menuItem -ex SuperMenuLab2`) deleteUI -mi SuperMenuLab2;
}
// You can then call that function when in the unload function of your plugin.

通过注册构建菜单项调用

您需要使用一个名为addMenuItemSafe的函数,它有三个参数:要填充的菜单、填充菜单的函数名称以及保存回调的全局变量名称。

首先要做的是创建一个函数来填充您的菜单,然后再创建另一个函数来移除它,最后调用AddMenuItemSafe方法。请注意,在函数中,您需要检查菜单是否已经创建,因为 Maya 会在每次显示菜单时都调用该函数。

首先,添加和删除菜单项的两个函数:

global proc string AddMyMenuItems()
{
    // Global variable to hold the test to see if the menu is populated.
    global int $gMyMenuItemsTest;

    // Menu var needed in our case because we are inserting in the middle of the menu
    global string $gMainFileMenu;

    if( $gMyMenuItemsTest == 0 ) 
    {
        // Actually build your menu.
        // Note that if you don't need to insert it after a specific entry,
        // You can just do `menuItem -label "blep"`. No need of -ia and -p
        // Also, for inserting in the middle you have to put stuff in reverse order.
        // If you are just appending, put it in the normal order.
        menuItem -label "Mylabel2" -insertAfter "someEntry" -parent $gMainFileMenu MyMenuLab2;
        menuItem -label "Mylabel" -insertAfter "someEntry" -parent $gMainFileMenu MyMenuLab;
        menuItem -divider true -parent $gMainFileMenu MyMenuDiv;

        $gMyMenuItemsTest = 1;
    }
    return "RemoveMyMenuItems()"; // Returns the callback
}

global proc RemoveMyMenuItems()
{
    global int $gMyMenuItemsTest;

    if( $gMyMenuItemsTest == 1 ) 
    {
        // Delete your items if they exist (yes we are kind of 
        // doing the check twice, but I find it safe. 
        // The user could have deleted it from Maya in the command
        // line for whatever reason, more robustness is always good.
        if(`menu -ex MyMenuDiv`) deleteUI -mi MyMenuDiv;
        if(`menu -ex MyMenuLab`) deleteUI -mi MyMenuLab;
        if(`menu -ex MyMenuLab2`) deleteUI -mi MyMenuLab2;
    }
}

接下来是对 AddMenuItemSafe 的实际调用:

// The menu we want to use ... here it is the File Menu.
global string $gMainFileMenu;

// Our variables needed for the addSafe call
global int $gMyMenuItemsTest;
global string $gMyMenuVariable;
$gMyMenuItemsTest = 0;
$gMyMenuVariable = "";

// The menu creation
addMenuItemSafe($gMainFileMenu, "AddMyMenuItems", "gMyMenuVariable");

您可以将该函数调用放在插件实例化或任何其他位置。
如需了解有关函数“AddMenuItemSafe”的更多信息,您可以进入Maya Scripts目录,在那里应该会找到“AddMenuItemSafe.mel”。
如何查找菜单名称 请注意,对于菜单变量名称,您可以使用以下约定“构建”它们

"g" + View + Name + "Menu"

其中:
- View是您可以在其中找到该菜单的视图。例如:Main、Polygons、Animations等。 - Name是菜单的名称。例如:File、Edit、Mesh等。 请注意,Autodesk有时会重命名菜单并使用旧的globalVariable名称,因此使用此方法可能不总是有效。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接