0

I am trying to make a plug-in that loads a menu with a simple print command attached to a button. I got two files:

  1. test_menu.py
import maya.cmds as cmds
import maya.mel as mel


def say_hello():   
    print('hello')


def menuui():     
    main_window = mel.eval("$retvalue = $gMainWindow;")
          
    custom_menu = cmds.menu('test_menu', label='test_menu', parent=main_window, tearOff=True)
    
    cmds.menuItem(label='say hello', command='say_hello()')
    cmds.setParent( '..', menu=True )
       
menuui()
  1. test_plugin.py
import maya.cmds as cmds
from maya.api import OpenMaya
import os

maya_useNewAPI = True

def load_menu(script_path):
    if os.path.isfile(script_path):
        with open(script_path) as f:
            exec(f.read(), globals())
            
def unload_menu():
    cmds.deleteUI(cmds.menu('test_menu', e=True, deleteAllItems=True))

def initializePlugin(plugin):

    plugin_fn = OpenMaya.MFnPlugin(plugin)    

    load_menu("C:/Users/Roger/Documents/maya/scripts/test_menu.py")
    

def uninitializePlugin(plugin):

    plugin_fn = OpenMaya.MFnPlugin(plugin)
    
    unload_menu()

When the test_menu.py is executed within the 'Script Editor' it works as expected. But, when executed as a plug-in it only loads the menu but when pressing the button it returns: # Error: NameError: file line 1: name 'say_hello' is not defined # .

It seems as if when loading the plugin maya executes it outside the scene?

The only workaround i've found. Which is quite horrible tbh is to add import test_menu before executing the command.

cmds.menuItem(label='say hello', command='import test_menu; say_hello()')

I would appreciate any help :)

RogerP
  • 1
  • 1
  • I'd say the solution you found is not `horrible` but the normal solution with python if you cannot import your menu script into the plugin script. You wrote a python module and then you import it and create your menu. I'd rather impor in your plugin script and call it from there. Your first way to load a fiel and run it with the exec() command is a very unusual way. – haggi krey Jul 09 '23 at 14:38

1 Answers1

0

The way I've dealt with custom plug-ins in Maya, is to use a module file.

In the Maya preferences folder, you need a plug-ins folder as well as a modules folder (just create them if they don't exist).

File structure

As an example, let's make a plug-in called foo. Start by creating the following file structure

modules/
    foo.mod

plug-ins/
    foo.py
    modules/
        __init__.py
        menu.py

Edit the files

foo.mod

+ PLATFORM:win64 Foo 1.0 ..\plug-ins\foo
MAYA_PLUG_IN_PATH +:= 

+ PLATFORM:mac Foo 1.0 ../plug-ins/foo
MAYA_PLUG_IN_PATH +:= 

+ PLATFORM:linux Foo 1.0 ../plug-ins/foo
MAYA_PLUG_IN_PATH +:= 

foo.py

import maya.api.OpenMaya as om
import maya.cmds as cmds

import modules.menu as menu


def maya_useNewAPI():
    pass


def initializePlugin(plugin):
    plugin_fn = om.MFnPlugin(plugin, 'RogerP', '1.0', 'Any')
    menu.create_menu()


def uninitializePlugin(plugin):
    menu.destroy_menu()

modules/menu.py

import maya.cmds as cmds
import maya.mel as mel


def create_menu():
    main_window = mel.eval('$tmpVar=$gMainWindow')

    menu = cmds.menu('foo', label='foo', parent=main_window, tearOff=True)
    cmds.menuItem(label='Print Hello', command=print_command)
    cmds.setParent('..', menu=True)


def destroy_menu():
    if cmds.menu('foo', exists=True):
        cmds.deleteUI('foo', menu=True)  # also deletes children


def print_command(*args):
    print('Hello')

Note that the command argument uses a reference to the print_command and NOT a string 'print_command()'. You can use partial if you want to pass arguments.

Morten
  • 487
  • 2
  • 13