Search code examples
pythonasciimayamel

Python function in Maya ascii file


I want to run some python code (function) as soon as I open .ma (maya ascii) file. So can i manually edit ma file and write some python code in it. so my question is how do I "Embed" python code in .MA file. MEL also fine. some mel code works, but not every. i don,t understand why it happens.


Solution

  • You should not be editing the files manually to do what you're trying -- MA files look like Mel but they aren't exactly the same, and you could easily break your scene with a bad edit.

    The standard way to embed script functionality in a Maya file is with a script node. For the application you're looking at you want to create a script node and set it up to run when the file is opened in Maya.

    The script node is created with cmds.scriptNode(). The node has two string attributes, .before and .after; you set one of these to the text of the script you want to execute. The .scriptType attribute is an enum which tells Maya when to execute the script and the .sourceType indicates whether to use Mel or Python. To run a script when the file is opened in Maya, you typically use .scriptType of 2, which is "On GUI open/close" and the .before attribute (which, a bit confusingly, is "beforeScript" in the command flags)

    So, for example, to print "hello world" when the scene is opened:

    sn = cmds.scriptNode(beforeScript = "print('hello world')")
    cmds.setAttr(sn + '.scriptType', 2) # gui open/close
    cmds.setAttr(sn + '.sourceType', 1) # python
    

    save the file and re-open, it will print 'hello world' to the listener. You don't have any control over the environment in which your file may be opened, so you should be careful about making assumptions about available imports and so on. The script will execute in the global scope, as if typed in the listener.

    update - packaging

    The comments indicate that OP wants to put more complex scripts into the node. Generally maya will execute the string as if you'd run exec on on the same string in Python. Exec works for multiline strings, but you have to format them correctly with newlines and tabs if you use tabs and spaces if not. You'll also need to escape your quotes correctly. For short scripts just use triple-single quotes to escape the whole thing:

    script = '''
    def example():
        for n in range (100):
            print ("hello world")
    example()
    '''
    import maya.cmds as cmds
    sn = cmds.scriptNode(beforeScript = script)
    cmds.setAttr(sn + '.scriptType', 2) 
    cmds.setAttr(sn + '.sourceType', 1) 
    

    Often it's easier to just read a script from disk and store it like this:

    def create_script_node_from_file(filename):
        with open('filename', 'rt') as handle:
            script_text = handle.read()
        sn = cmds.scriptNode(beforeScript = script_text)
        cmds.setAttr(sn + '.scriptType', 2) # gui open/close
        cmds.setAttr(sn + '.sourceType', 1) # python
    

    You probably don't want to do anything very intrusive or elaborate in a script node because people opening the file in the future may only want to inspect it and not get deep into whatever UI you are presenting. You may also make it harder to run batch processes on the file.