Home Technical Talk

(Solved) MEL mystery series

polycounter lvl 6
Offline / Send Message
bitinn polycounter lvl 6
People of knowledge, please help me to understand this:

In Maya LT 2017 + macOS, I have following test script:


In full:

// REMEMBER TO SOURCE THIS, NOT RUN IN THE SCRIPT EDITOR DIRECTLY
{
    string $TEST_STRING = "TEST_STRING_#";
    proc RunLocal1 () {
        print($TEST_STRING);
    }
    proc RunLocal2 (string $Input) {
        print($Input);
    }
    proc RunLocal3 () {
        RunLocal2($TEST_STRING);
    }
    global proc RunGlobal () {
        // uncomment this, click button, print "".
        //RunLocal1();
        // uncomment this, click button, error "Error evaluating argument at position 1 in procedure RunLocal2".
        //RunLocal2($TEST_STRING);
        // uncomment this, click button, Maya crashes.
        //RunLocal3();
    }
    global proc CreateWindow () {
        if (`window -exists "TestWindow"`) {
            deleteUI "TestWindow";
        }
        window
          -title "Test"
          -sizeable 0
          -maximizeButton 0
          -widthHeight 200 100
          "TestWindow";
        string $TestButtons = `frameLayout
          -collapsable 0
          -labelVisible 0
          "TestButtons"`;
        rowColumnLayout -numberOfRows 1;
        button
          -label "Quick Test"
          -command "RunGlobal";
        showWindow "TestWindow";
    }
    CreateWindow();
}

Can you reproduce my issues mentioned in the script's comments?
 
IF SO, why?
 
How do I make a local variable that's available to a global proc being invoked through UI?

Replies

  • bitinn
    Offline / Send Message
    bitinn polycounter lvl 6
    I believe this is the only safe alternative (to using global/local variables).

    If you are using MEL script, good luck trying to share a variable across procedures!

    (It would work in your script editor, but as soon as you try to invoke global proc through UI, as "-command" requires global proc, shits goes down because of context change).

    Only local proc is fully protected from lost of context during the UI invoke, as far as I can tell. Variables are lost.

    https://gist.github.com/bitinn/b2e32975e2b39a08d58c4d5758d22e94
    // REMEMBER TO SOURCE THIS, NOT RUN IN THE SCRIPT EDITOR DIRECTLY
    {
        proc string GetTestString () {
            return "TEST_STRING_#";
        }
    
        proc RunLocal1 () {
            print(GetTestString());
        }
    
        proc RunLocal2 (string $Input) {
            print($Input);
        }
    
        proc RunLocal3 () {
            RunLocal2(GetTestString());
        }
    
        global proc RunGlobal () {
            // works
            print (GetTestString());
    
            // works
            RunLocal1();
    
            // works
            RunLocal2(GetTestString());
    
            // works
            RunLocal3();
        }
    
        global proc CreateWindow () {
            if (`window -exists "TestWindow"`) {
                deleteUI "TestWindow";
            }
    
            window
              -title "Test"
              -sizeable 0
              -maximizeButton 0
              -widthHeight 200 100
              "TestWindow";
    
            string $TestButtons = `frameLayout
              -collapsable 0
              -labelVisible 0
              "TestButtons"`;
    
            rowColumnLayout -numberOfRows 1;
    
            button
              -label "Quick Test"
              -command "RunGlobal";
    
            showWindow "TestWindow";
        }
    
        CreateWindow();
    }


  • bitinn
    Offline / Send Message
    bitinn polycounter lvl 6
    Final words from Autodesk: you can't use an anonymous {} to fake a block scope man, that's against the rules!

    - So (1) me getting OP's script to work is a bug in MEL.

    - And (2) Autodesk senior engineer advise the solution is to use global variable, even though we programmers and the Maya doc both agree global variables are pretty bad.

    (Think my Reply's solution still taste better than a bunch of global variables...)
  • sprunghunt
    Offline / Send Message
    sprunghunt polycounter
    The  way I pass variables around with mel -  without using global variables - is with return values that feed into new variables. So I do a lot of this kind of thing

    <br>global proc string TestString(){
        //here you output the variable<br>&nbsp; &nbsp; return "some text";<br>}<br><br>global proc GetString(){<br>&nbsp; &nbsp; //here you access the variable<br>&nbsp; &nbsp; string $newString = ` TestString()`;<br>}<br>

  • claydough
    Offline / Send Message
    claydough polycounter lvl 10
    Saying global variables are bad is like saying script Jobs are bad.
    Neither are bad...
    Neither are a failure. 
    Global Variables do not kill people or cause bugs yadda yadda...

    Any tech artist of any worth leverages as much to great advantage when appropriate.
    Stop speading this myth!

    They are a consideration not a sin! Never were!
    One could admit, " I am jes to stupidz to use script jobz o global variablez! "?

    But since 1999 I have yet to have an issue using a global Variable in the past 18 years! ( kind of ridiculous imagining not leveraging as much all that time? )
    I imagine because as much is obviously a consideration...
    One is simply more careful planning for and deciding upon their usage? 
    Same with scriptJobs... 
    ( sans getSelectionInOrder biting me in the ass early on. But one simply learns to take care. Bugs are usually logic error either way... not inherent evil code whose sins are to unholy to b addressed )

    Otherwise there are probably billions of ways to pass a variable ( which is just data in the end )

    Write it to a file
    make it a preference ( optionVar it )
    store it in a vertex via color! ( blind data that can even be connected and reflect new data )
    store it in a connectible attribute! ( with all the added benefit that connectAttr and set driven key brings to the table )
    Echo it! ( scriptEditorInfo -historyFilename "cly_tempHistoryLog.txt" -writeHistory true; )
    Store it in a UI ( annotation, label etc.. )

    These are the hacks that makes one giggle at 3 am...
    when one realizes that in the scope of a function one can easily store vertex selection order in blind data color even after "most" vrt order destructive edits change the vrt order ( store vrt by position instead of implicitly queried!
    through it's blind data color which remains constant by position )
    ( Same vrt order trick is stored in selection sets which is slightly cheaper and allows for boolean selection comparisons )
  • bitinn
    Offline / Send Message
    bitinn polycounter lvl 6
    claydough said:
    Saying global variables are bad is like saying script Jobs are bad.
    Neither are bad...
    Neither are a failure. 
    Global Variables do not kill people or cause bugs yadda yadda...

    Any tech artist of any worth leverages as much to great advantage when appropriate.
    Stop speading this myth!

    They are a consideration not a sin! Never were!
    One could admit, " I am jes to stupidz to use script jobz o global variablez! "?

    But since 1999 I have yet to have an issue using a global Variable in the past 18 years! ( kind of ridiculous imagining not leveraging as much all that time? )
    I imagine because as much is obviously a consideration...
    One is simply more careful planning for and deciding upon their usage? 
    Same with scriptJobs... 
    ( sans getSelectionInOrder biting me in the ass early on. But one simply learns to take care. Bugs are usually logic error either way... not inherent evil code whose sins are to unholy to b addressed )

    Otherwise there are probably billions of ways to pass a variable ( which is just data in the end )

    Write it to a file
    make it a preference ( optionVar it )
    store it in a vertex via color! ( blind data that can even be connected and reflect new data )
    store it in a connectible attribute! ( with all the added benefit that connectAttr and set driven key brings to the table )
    Echo it! ( scriptEditorInfo -historyFilename "cly_tempHistoryLog.txt" -writeHistory true; )
    Store it in a UI ( annotation, label etc.. )

    These are the hacks that makes one giggle at 3 am...
    when one realizes that in the scope of a function one can easily store vertex selection order in blind data color even after "most" vrt order destructive edits change the vrt order ( store vrt by position instead of implicitly queried!
    through it's blind data color which remains constant by position )
    ( Same vrt order trick is stored in selection sets which is slightly cheaper and allows for boolean selection comparisons )
    Hi @claydough, since you have been programming 1999, may I ask if you have ever programmed in a language with proper OOP/FP?

    It's cool you can figure out many ways to workaround MEL's limit, but they are workarounds:

    - Write it to a file (IO)
    - Make it a preference (intended for cross-session data sharing)
    - Store in a vertex (rely on scene objects)
    - Store in a connected attribute (ditto)
    - Store in a UI (ditto)
    - Echo it (is echoing writable?)

    To come in and say I am spreading a myth about global variables, you should read their doc and their principal engineer's words first.


    -


    There are difference between "accepting the limit of MEL" and "defending its outdated paradigm to teeth".

    Enjoy your day, mate.
  • r3Dmond
    Offline / Send Message
    r3Dmond polycounter lvl 4
    I know I'm reviving an old post here but I would like to thank you bitinn 

    I've encountered the same exact bug while working on a script these past few days and it caused some serious headache! I'm new to programming, so a lot of things are still beyond me, but like yourself I usually prefer to encapsulate everything within brackets.

    I honestly couldn't find much information regarding this behavior and figuring things out on my own wasn't trivial. Working from intuition I finally understood what was going on and opted, begrudgingly, to make variables common to all my procedures global, which fixed my UI issues.

    Your post confirmed my assumptions and now at least I have a better understanding of the problem. I'll experiment with other ways of passing variables through procedures because I'm not fond of the "global" solution.

    Also thank you for linking your post on the Autodesk Forums. Even kevin Picott admits this is a bug, I think that puts the issue definitely at rest.
Sign In or Register to comment.