Showing posts with label Coding. Show all posts
Showing posts with label Coding. Show all posts

Friday, March 5, 2010

Efficient Scripting In MEL - Part II

TL;DR - Make your own MEL procedures that are better versions of existing commands if it will speed up your workflow. Some of the default MEL commands are lacking.

This next article is a bit more about scripting and programming in general and less about MEL specifically. It's about using procedures to take care of basic functions in order to speed up tasks you perform regularly in your scripts.

Let say for example you want to print out some data. In MEL and most languages I've programmed with, when you print or echo something it will not create a new line the next time you print. So if you print the phrase "Hello World" twice in a row, it will look like this: "HelloWorldHelloWorld".

So, a quick and easy way to do this is to add a newline. To do this in MEL, you use the characters "\n". So your print statement looks like this:

print "Hello World\n" ;
print "Hello World\n" ;
// Result:
// Hello World
// Hello World
//
// Without \n you'll get:
// Result: HelloWorldHelloWorld

When you need to add a newline character onto every single thing you print it can get time-consuming. Especially when you need to concatenate it with a variable which in turn you then need to add parenthesis around your entire statement, it's very annoying. We know every millisecond counts right? So let's save ourselves some time and build a custom print statement.

// **********************************************************
// Faster way to print
global proc jgPrint (string $print) {
print ($print+"\n") ;
}

// Now I can simply call:
jgPrint "Hello World!" ;

// And it adds the newline for me.

Slightly unrelated, but another benefit to this method is that you can print a concatenated int or float with a string argument using this method which you can't with a normal print statement.

So there we've created a small procedure that will save us lots of time down the road. Essentially we're creating tools to help perform tasks faster than we could without them, and filling in gaps with tools that the default language doesn't provide or where the default commands are lacking in one way or another.

There are an infinite number of ways you can use these. I'm not going to provide all the code for you since it's a good learning experience to write these on your own...but here are a couple examples of some procs I use on a daily basis.
  • Append A Single String Argument To A String Array
  • Read A Text File And Return It As A String Array
  • Create A Set Driven Key
  • Make An Attribute On An Object
  • Edit An Attribute's Values
  • Pass An Array Into A String Argument
These are all things that already have built-in Maya commands but are either unintuitive to use or are just plain annoying and slow. There are no rules that say you need to do it the "right" way or the way Maya wants you to. If you can get the job done faster by making your own commands or procedures than go for it!

Thursday, March 4, 2010

Efficient Scripting In MEL - Part I

TL;DR - The less lines in your code the better, and use argument passing tricks whenever possible. Keep it clean!

After talking to a coworker today about how it'd be cool to try and rewrite a script he made in only ten lines of code...I thought it'd be good to to write a short post about how to increase efficiency in your MEL scripting. By efficiency, I mean saving yourself time both in the creation and the editing of your code by condensing your scripts into shorter blocks and not using more lines than you need to. I've found that it helps me a lot in the long term when my scripts are much shorter and easier to edit. On top of that, it's just way more awesome to write a script in ten lines that does the exact same thing as one that does it in fifty.

We'll start with some simple examples:

Let's start with a FOR Loop. Normally you'd setup a FOR loop like this:

for($i = 0; $i < 10; $i++) {
print $i ;
}

Or like this..


for($item in $myArray){
print $item ;
}

But why not condense it? Let's put that three lines of code into one.


for($item in $myArray) print $item

It doesn't seem like much of a gain, but in actuality you've cut the size by 66%.

Now let's add an IF statement to this line..


for($item in $myArray) if($item == "myItem") print $item

Still one line of code but you've got another check in there.

Another example, check if an object exists, error out if not.

int $exists = `objExists $myObject` ;
if(!$exists) {
error "Object doesn't exist." ;
}

// Four lines? Bleh. Let's bring it down a few..

if(!`objExists $myObject`) error "Object doesn't exist." ;

Some more error check examples:

if(!`filetest -f $pathToFile`) error "File does not exist." ;
//
if(!`endsWith $mayaFile ".mb"` && !`endsWith $mayaFile ".ma"`) error "File is not a Maya file." ;
//

This helps a lot when you've got a procedure that has a lot of error checking. Don't allow your checks to steal all of your screen real estate. Condense them into one line and celebrate your awesomeness with a frosty pint.

What about when you need to get some data from a textField or any other control? Assuming it returns a string, and not a string array. You condense the following:

string $myText = `textField -query -text myTextField` ;
print $myText ;

// Pffffff.

print `textField -query -text myTextField` ;

// Much better!

So this is a short, basic look into how to do this sort of stuff. I find that although making your code cleaner and nicer is probably in the top ten nerdiest things possible, you'll appreciate it someday when you look step back and look at your script and actually smile at how cool it looks. It is after all an art form. :)

Tuesday, March 2, 2010

MEL: Run A Command Line Program Through Maya

Ever needed to run an executable/command line app from Maya? You can use the "system" command to do this.


system("echo \"Hello World!\"") ;
// Result: "Hello World!"

So, if you need to use your maya data to run through an executable for any reason, you can use the system command the same as you would with any Maya procedure.

Random Example:

string $numVerts = "2023" ; // Number of vertices on a mesh
string $mesh = "myMesh" ; // Mesh Name
system("C:/myAppDirectory/mySpecialVertApp "+$numVerts+" "+$mesh) ;

This allows you to gather data in a Maya scene and send it directly to your executable without needing to save it out first. It's a bit slower than running it normally, but barely noticeable.

Friday, February 19, 2010

MEL: Source A Script With A Variable

Maya's MEL script command "source" will not let you source a path through a variable. Example, the following will NOT work.


string $myScriptPath = "C:/myScript.mel" ;
source $myScriptPath ;

It will produce a syntax error. So, how do we do it then? One method is by using the "eval" command and putting the source command into the string itself and slashing out the quotes.


string $command = "source \"C:/script.mel\" ;" ;
eval $command ;

"eval" will run the string as a command, thus sourcing it and your script/variable.

Another option here is to create your own proc, let's call it betterSource() ;


global proc betterSource (string $script) {

string $command = "source \""+$script+"\"";
eval $command ;

}

// Now you can run:

string $path = "C:/script.mel" ;
betterSource $path ;

Either way works and one is not necessarily better than the other.

Thursday, February 11, 2010

MEL: Snap / Move An Object To The Position and Orientation of Another Object

There's a super easy trick for snapping an object to the position and orientation of another object in your scene.

All you need to do is constrain your object with maintain offset turned off, and then delete the constraint. So, a quick and easy way to do this with point and orient constraints.


delete `pointConstraint $obj $targetObj` ;
delete `orientConstraint $obj $targetObj` ;

This deletes the return (the name of the constraint) after running the constraint itself.

Similarly you could just use a parent constraint.

delete `parentConstraint $obj $targetObj` ;

Credit to John Riggs for showing me this trick.

Wednesday, September 30, 2009

MEL: Print Size Of Your Current Selection, Or Print Your Current Selection

There are a few different ways to print out the size of your selection.

To print the size of your selection:

// Simply use the size command combined with the return of the list selected command
size(`ls -selection`) ;

To print what is currently selected:

// Use the LS command to list your selection
ls -selection ;

// Or print it... (same thing)
print `ls -selection` ;
// What about vertices? (faces, etc.)
// ls -selection ; will usually return a next to useless result with multiple verts selected.
// Instead add another flag, -flatten
ls -selection -flatten ;

Any questions? Please comment below.

Scripting Topics

MEL (41) Maya (39) Scripting (32) Scripts (21) programming (14) Free Mel Scripts (8) MaxScript (7) Coding (6) Rigging (5) tutorial (5) 3ds Max (4) Python (4) Tricks (4) faceware (4) image metrics (4) Learn (3) Namespace (3) Namespacing (3) animation (3) facial (3) webinar (3) Code (2) GDC (2) Game Developers Conference (2) Multiple Namespaces (2) Print Selected Objects (2) Recursive (2) Removing Namespace (2) Return (2) Set Driven Keys (2) TOkenize (2) Tips (2) Toggle Background Color with MEL (2) animation tools (2) animators resource (2) deformers (2) learning (2) maya tools (2) mesh (2) modeling (2) nodes (2) procedure (2) script swell (2) transforms (2) Animschool (1) Attribute (1) Background Color (1) Beer (1) Blur (1) Character Setup (1) Check if an object exists (1) Class (1) Command Line (1) Constraints (1) Create SDK (1) Create a directory with mel (1) Data (1) Export (1) FilterString (1) Fix (1) Floating Slider Time (1) Functions (1) Get Maya Version MEL (1) Get Parent (1) Google (1) Holiday (1) How To Write To A Text File (1) Import (1) Incremental Save (1) Index (1) Joint Chain (1) Make Set Driven Keys (1) Maya Version (1) Modules (1) Objects (1) Orient Constraint (1) PYMEL (1) Parent (1) Parent Constraint (1) Point Constraint (1) Position (1) Print (1) Print Current Selection (1) Print Random Quotes (1) Print Selection (1) Print Vertices (1) Progress Bar (1) Progress Window (1) PyQT (1) Removing Spaces From Names (1) Scene File Name (1) Select Connections (1) Select Outgoing Nodes (1) Split Bones (1) Split Joints (1) St. Patrick's Day (1) String Array (1) System (1) Transfer UVs (1) Viewport (1) White Space (1) Windows Username (1) Zero Out Attributes (1) animButtonState (1) arrays (1) articles (1) auto key (1) better (1) blendshapes (1) break (1) confirm dialog (1) continue (1) convention (1) e3 (1) efficiency (1) error (1) eval (1) executable (1) fclose (1) fopen (1) fprint (1) games (1) improving (1) infinite loop (1) joints (1) listHistory (1) listRelatives (1) logic (1) loops (1) milestone (1) nodeType (1) objExists (1) recursion (1) rotates (1) rotations (1) schools (1) sculpting (1) setAttr (1) shout outs (1) source (1) source a script with a variable (1) speed (1) tech-artists.org (1) translates (1) video (1) warning (1) world matrix (1) worldMatrix (1)
 
Script Swell - Blogged