Search code examples
pythonpython-2.7maya

Maya : ScriptNode pop up menu with error "invalid directive"


I am writing a GUI and script that execute when a specific object is selected in the scene. I was not having any issues before, but now I am...

When I select my object, a scriptJob I created says to launch the program... At this point, it doesn't. Taking a further look into it, I tried to test the scriptNode, which results in:

// Error:  //
// Error: Line 0.0: invalid directive //

Now, I originally had this issue due to stray ";" in my comments. I removed every semicolon I could find... It worked once and then stopped working.

=========================================================================

Another addition... I've removed all the comments from my script to embed, and it is now calling out my classes as syntax errors. See below:

// Error: class x2m_info: //
// Error: Line 9.15: Syntax error //

I should also include that running the script normally DOES make it work normally. This is strictly running it as a scriptNode and scriptJob.

============= Below is an attempted replication ==============

# Below is a saved py file, its mother file is similar and run in Maya
# Let us say it is saved in this dir, "D:\\USER\\JAMES\\" as "coolscript.py"
import modules # a list of modules, os, sys, subprocess, etc.
class numberOne: # Interpret this as the x2m_info class I specified above
    def about_info(self, x):
        # Does stuff
        if x==1:
            print("Does stuff, like display information: %s" % x)
        else:
            print("Does stuff, like display contact info: %s" % x)
    # Has a few more similar functions

class something:
     def func1(self, x):
         numberOne().about_info(1)
     def func2(self):
         numberOne().about_info(2)
def main():
    something().func1(1)
    something().func1(2)

import maya.cmds as cmds
# Portion in Maya that takes this and embeds it
embedThisFile = "D:\\USER\\JAMES\\coolscript.py"
embeddedStr   = open(embedThisfile, "r")
embed         = embeddedStr.read()
cmds.scriptNode(name="WhereToEmbed", beforeScript=embed, scriptType=1, sourceType="python")

scriptToVar   = cmds.scriptNode("WhereToEmbed", query=1, beforeScript=1)
scriptJobName = cmds.scriptJob(conditionTrue=("SomethingSelected",
                               "if (cmds.ls(selected=1)[0]) == 'pCube1':\
                               exec('%s'); main()" % (scriptToVar)),
                               killWithScene=1, protected=1)

Solution

  • Your approach is perfectly legal in Maya.

    Translating mel code into Pymel

    Most of us learn Maya commands by monitoring the script editor. It prints commands in Maya. There is a certain order when you translate mel code into python. First let's see the mel command sample for scriptJob. You can find sample code at the very bottom of the page. See this sample code line:

    //create a job that deletes things when they are seleted
    int $jobNum = `scriptJob -ct "SomethingSelected" "delete" -protected`;
    

    -ct flag is the shorthand for for conditionTrue.

    {flag} -ct {space} {first parameter} "SomethingSelected" {space}
                  {second parameter-this is the command to execute} "delete". 
    

    So when you translate this command into pymel we have to follow the following order:

    cmds.command(flag_1=paramaters,flag_2=paramaters,.......,flag_n=paramaters)
    

    When you have to pass multiple flags, you must put them into an array, list or tuple. They must follow the correct order. Usually the object name is the first parameter.

    cmds.command(flag=[parameter_1,parameter_1,....,parameter_n])
    

    So in your case:

    scriptJobName = cmds.scriptJob(conditionTrue=["SomethingSelected",
        "if (cmds.ls(selected=1)[0]) == 'pCube1':exec('%s'); main()" 
        % (scriptToVar)], killWithScene=1, protected=1,)
    

    conditionTrue = [condition,yourScript]

    However, if the conditions you've placed are all correct, it can help to change how the code is being run on the inside of the scriptJob. Mainly:

    exec('%s')
    

    Should be:

    exec('''%s''')
    

    Accounting for any comments, line breaks, returns, or semi-colons in the code that is being embedded... The triple quote acts as a comment block, which in turn, helps process the entire code as it truly is.

    In your sample code the syntax error is that Maya doesn't see a code to execute for the condition. The Invalid directive is that Maya cannot process the code and hangs up at a point, as it is trying to process the command as a directive (MEL terminology for a "flag").

    This is all explained by incorrectly nesting quotes. Though what you did was legal and viable, if you have comments ("#"), semi-colons (";"), and new-lines and returns ("\n","\r", respectively), it is better to provide a block comment... The single / double quote may conflict with that information that is already in your code and will incorrectly split up your code.

    This should resolve your problem.

    For more information on scriptJobs in pyMel, look below:

    see the sample pymel code for scriptJob