Showing posts with label tutorial. Show all posts
Showing posts with label tutorial. Show all posts

Thursday, July 7, 2011

Webinars & Videos

Script Swell now has a widget with links to the webinars and tutorial videos I've been working on the last couple of months. So far they are all in the realm of facial animation and rigging, along with my Faceware demo from GDC this year. As I make more videos I'll keep the links updated. The links take you to YouTube, though you can also find them all on Vimeo if that is your preferred site.


Tuesday, March 22, 2011

MEL/MAXScript Tutorial Requests

I've been wanting to write another MEL and/or MAXScript tutorial lately, but I'm not sure yet what topic(s) I want to cover. There's plenty of MEL commands and techniques and other stuff I could do but I figured I'd put out a call and see if anyone had some specific requests. Leave a comment if you have an idea for a tutorial that you'd like to see.

Wednesday, December 8, 2010

MEL Scripting Tutorial: How To Write To A Text File

In this mel scripting tutorial we'll look at how to write data out to a file so you can make your own data exporting tools. By the end of it you'll have a firm understanding of and know how to take data from your Maya scene and write it out to a file. This is a follow up to the previous tutorial: How To Read A Text File. This article assumes you've read the previous tutorial and is a continuation of the concepts discussed in it. If you've not read the tutorial on how to read a text file, please browse Script Swell's Technical Artist Tutorials or click here.

Skill Level: Beginner to Intermediate

There are two things you'll need in order to proceed: some data to write out, and a text a file to write it to. To start off let's create a string array in Maya. In the script editor, copy and paste the following and run it.
// Create A String Array With Test Data
string $myStrArray[] = {"This is line one of my data from Maya.", "This is line two.", "And then line three!"} ;
Next, create a file in an easy location, e.g. "C:\mel\testFile_v01.txt". In this file, on the first line type the following: "This is the first line of my text file, version 01!". Save and close your file.

Now let's get into some code and see how this works. The idea here is that we're going to "open" our file as an object in Maya, put our data inside it, then "close" it. If you recall in the previous tutorial we use the fopen command to open the file and prepare it for use.
// Create A String Array With Test Data
string $myStrArray[] = {"This is line one of my data from Maya.", "This is line two.", "And then line three!"} ;

// Define Your File Path
string $filePath = "C:/mel/testFile_v01.txt" ;

// Open Your File
$fileId = `fopen $filePath "a"` ;
The first difference you may have noticed from the previous tutorial is that instead of "r" (for 'read') we've switched to "a" which stands for "append". What this means is that we're telling MEL that when we're working with this particular file, we'll be writing to it but we'll be appending data onto the end of whatever is there. This way using the "a" flag you can keep your current data intact and simply add more to it. Let's continue on with more code.
// Create A String Array With Test Data
string $myStrArray[] = {"This is line one of my data from Maya.", "This is line two.", "And then line three!"} ;

// Define Your File Path
string $filePath = "C:/mel/testFile_v01.txt" ;

// Open Your File
$fileId = `fopen $filePath "a"` ;

// Print Array To File
for($line in $myStrArray)
fprint $fileId ($line+"\n") ;

// Close File
fclose $fileId ;
The newest line in our code starts with a for in loop and is looping through our string array one line at a time. This is because in this case we don't just want to dump all the data to the file, we want to have control over how it's added and make sure it's exporting to an easily readable format. We loop through our array one line at a time and use the fprint command. What fprint does is essentially the same thing that the normal print command does except it prints to your text file instead of Maya's script editor. Just like print though, it will not add a new line at the end of the argument and this must be done manually, hence the "\n" that I've appended to the $line variable. If you leave this out, all of your data will print to a single line! After we're finished printing out the data we're using fclose to "close" our file object.

-----------------------------------------------------------
Tip: If you forget to use fclose and leave the file object "open" within Maya it will become locked and you won't be able to make changes to it outside of the program. If this happens you will need to close Maya to "unlock" your file.
-----------------------------------------------------------

After running this script, take a look at your text file and you'll see the file now reads the following:
This is the first line of my text file, version 01!
This is line one of my data from Maya.
This is line two.
And then line three!
Nicely done! You are now one step closer to building your data export tool. Next we'll double back slightly and look at another flag we can use in the fopen command. Look at the code below.
// Create A String Array With Test Data
string $myStrArray[] = {"This is line one of my data from Maya.", "This is line two.", "And then line three!"} ;

// Define Your File Path
string $filePath = "C:/mel/testFile_v01.txt" ;

// Open Your File
$fileId = `fopen $filePath "w"` ;

// Print Array To File
for($line in $myStrArray)
fprint $fileId ($line+"\n") ;

// Close File
fclose $fileId ;
The only change here is we've swapped the "a" flag with it's brother: "w" which stands for "write". What write will do is destroy the prior contents of the file and replace them with whatever we're printing to it. So your result will be:
This is line one of my data from Maya.
This is line two.
And then line three!
This time only the string array has been printed to the file and the original file's contents were destroyed.

Both of these flags are useful depending on the context of what you're doing. Be sure to check out these commands in the MEL documentation as well for a slightly more in-depth look at how they work.

It really is simple as that to write out data! As long as you remember to fclose your file and use the correct flags when using fopen you shouldn't have any trouble using this technique.

For more tutorials check out the Technical Artist Tutorials page. Leave a comment below if you have any thoughts or questions and thanks for reading!

Sunday, October 17, 2010

MEL Scripting Tutorial: How To Read A Text File

This is a scripting tutorial that will show you how to use MEL to read a text file and use the data from it in Maya. As a scripter it's an essential skill to have. A lot of times there will be data you need in a file that's outside of your program and you'll need to get it. The file may contain animation data you need to access, skin weighting data, a list of objects needed in a scene or any other type of data you could imagine a text file having. This tutorial assumes you have a basic understanding of MEL syntax and how to run a script in Maya.

Skill Level: Beginner to Intermediate

First off we need a data file to test with, so let's make one. Open up your favorite text editor (notepad will work if you don't have anything else), create a new .TXT file. and save it somewhere as "myDataFile.txt". For this lesson, I recommend saving your file somewhere with a relatively simple file path, e.g. "C:\mel\myDataFile.txt".

Copy and paste the following data into your file and save:

//objectName,posX,posY,posZ,rotX,rotY,rotZ,scaleX,scaleY,scaleZ
pCube1,0,0,0,0,0,0,1,1,1
pSphere1,-5,10,-5,-90,90,-45,1,1,1
pCylinder1,2.5,2.342,4.2823,0,0,0,1,1,1
pPlane1,0,0,0,360,180,45,1,1,1

-----------------------------------------------------------
Tip: The file doesn't necessarily have to use a .TXT file extension. Any text-based file format will work the same way. You can even make up your own file extension. I like to use .RIG files.
-----------------------------------------------------------

Now that we have a file to test with let's look at what's in it. It's important to look at what type of data you're working with so you can plan on how to bring it in and in what format you'll need it to be in once it's in Maya.

In this case there are multiple lines of text, with each line having ten values separated by commas. We refer to this type of data as comma-separated. Our example has the name of an object and it's nine transform values (translate X,Y,Z, rotate X,Y,Z, scale X,Y,Z). Note that the first line doesn't have any actual values, it just serves to tell us what each value represents. This is common in data files. You may need to adjust your script to skip the first line when it brings in the data.

Using this data we're going to find the objects in our Maya scene and set their transforms. Let's get to it!

The first part of our script is putting the path to the file we just created into a string variable.


// Define Your File Path
string $filePath = "C:/mel/myDataFile.txt" ;

-----------------------------------------------------------
Tip: File paths in Maya (and most packages) require that you use forward slashes (/) instead of backslashes (\). You will get errors if you use backslashes.
-----------------------------------------------------------

Now that we have the path saved in $filePath we're going to use a MEL command called fopen . This command tells Maya to find the file and open it and also tells Maya what we're going to do with the file. There is an optional string argument (I recommend always using it) that will tell Maya if you're going to just read the file, write to it, or append to the end of the existing file. Check out the MEL Documentation for a more in-depth description on how these work, but for now just be aware that since we're reading the data from the file, we're going to use "r" for read.

// Open Your File
$fileId = `fopen $filePath "r"` ;

With the line of code above we've stored our "open" file into the variable $fileId. Now anytime we want to refer to that file in our script we can refer to $fileId. By using the "r" string in the command we've also told Maya that it only has permission to read from the file and nothing else. This way we don't have to worry about the file being changed in any way.

-----------------------------------------------------------
Tip: In the fread command, besides "r" (read), you can also use "w" (write) or "a" (append). More on this in the next tutorial.
-----------------------------------------------------------

Now that the file is open, let's interact with it. There are two commands we're going to look at in this tutorial. The first command is fread. This is used in the following way:

// Read The Data Using fread
string $data = `fread $fileId $data` ;

The usage is a little odd since we're simultaneously defining a string variable and using it as an argument in the command, but this is the way fread works. What it will do is take all of your data in the file and return it as a single string. In this case our return string value would be:

// Result: objectName,polygonType,posX,posY,posZ,rotX,rotY,rotZ,scaleX,scaleY,scaleZ
pCube1,0,0,0,0,0,0,1,1,1
pSphere1,-5,10,-5,-90,90,-45,1,1,1
pCylinder1,2.5,2.342,4.2823,0,0,0,1,1,1
pPlane1,0,0,0,360,180,45,1,1,1//

Nice! All of the data from the text file is in Maya! Success!

The only problem is...ALL of that information is in a single string. It's not much use to you in this format since the actual data is dense and on multiple lines. If you really wanted to you could take that string and break it up into all of the data you need (a mixture of loops and heavy usage of MEL's tokenize command)...but there's an easier way to handle it. There is another command we can use called fgetline.

The fgetline command will get a single line of data from the file and put it into a string variable. This becomes useful because we can now create a string array and put each line into it separately. This will give us a string array containing our entire text file.

The only hiccup here is fgetline will simply get one line of text and then stop. It's not smart enough to continue through the whole text file, we have to tell it to do that. We do this with a WHILE loop. Check it out below ...let's combine everything we've done so far:

// Define Your File Path
string $filePath = "C:/mel/myDataFile.txt" ;

// Open Your File
$fileId = `fopen $filePath "r"` ;

// Get The First Line
string $nextLine = `fgetline $fileId` ;

// Loop Until The String Size Is Zero (No Data)
while (size($nextLine) > 0) {

// Strip Whitespace From The Beginning And End Of The Line
string $cleanLine = strip($nextLine) ;

// Print Line
print ($cleanLine+"\n") ;

// Get Next Line And Continue
$nextLine = `fgetline $fileId` ;

}

If you run this, you'll see Maya print out the five lines of our text file. This time, each of those lines was printed one at a time. Ultimate success!

Let's make a few more additions and turn this into a procedure. First I want it to return an array, so I'm going to define a string array and then put each of my lines into it when I get them from the text file. Next I want to add an argument to tell it to skip the first line. This is useful if I know the first line of my file contains data I don't want. Lastly, instead of hard coding the path into the function, I want to pass the file path into my procedure as an argument to make it more versatile.

When we're finished our procedure looks like this:

// **********************************************************
// Reads A Text File And Returns A String Array Of Each Line
global proc string[] jgTextFileToStringArray (int $skipFirstLine, string $filePath) {

// Open File
$fileId = `fopen $filePath "r"` ;

// Define String Array
string $dataArray[] ;

// Get The First Line
string $nextLine = `fgetline $fileId` ;

// Loop Until The String Size Is Zero (No Data On That Line)
while (size($nextLine) > 0) {

// Strip Whitespace From The Beginning And End Of The Line
string $cleanLine = strip($nextLine) ;

// Add To Array
$dataArray[size($dataArray)] = $cleanLine ;

// Get Next Line And Continue
$nextLine = `fgetline $fileId` ;

}

// Remove First Line
if($skipFirstLine) stringArrayRemoveAtIndex(0,$dataArray) ;

// Return Array
return $dataArray ;

}

Check out the finished version here:
jgTextFileToStringArray.mel

The next tutorial will extend on this and go over how to write to and append to a text file.

Leave a comment below if you found this helpful or have any questions.

Looking for more tutorials? Check out Script Swell's Technical Artist Tutorials page.

Saturday, March 20, 2010

MEL Scripting Tutorial: Using The Tokenize Command

This MEL scripting tutorial will give you an in-depth look into how to use the tokenize command. Tokenize is used for taking a string and breaking it up into a number of parts so they may be used on their own. It's one of the most commonly used commands in the language and a strong knowledge of how to use it will help anyone write better procedures. This tutorial assumes a basic knowledge of running a MEL script in Maya.

Skill Level:
Beginner

The tokenize MEL command is incredibly useful and very easy to use. You'll find once you know how it works and what it does, you'll end up using it in almost every script you write in one way or another. What tokenize does is essentially break a string up into different parts based on a splitter character, and return them into an empty string array. Why would you need to break up a string into different parts? There are many reasons you may need to do this. An example being let's say you're string is an Object.Attr and you need to parse out just the attribute, or perhaps just the object. You can use tokenize to split them up into their own strings. Maybe you have a path to a file and you want to tokenize it by slashes. Or, you have a comma-separated line of text and you want to split each field into an array. There are countless ways to use it and I think you'll find once you know how to use it, you'll use it constantly. Let's look at some examples:

"myObject.translateX" would tokenize into "myObject" and "translateX". Here's how we would do that:

// Here is our string, in the variable $myString
string $myString = "myObject.translateX" ;

// First we create an empty string array, to play our "parts" in.
string $buffer[] ;

// Now we'll tokenize our string and put the tokens into $buffer
tokenize $myString "." $buffer ;

// Notice the arguments: string, splitter, array.

// Now if we print out $buffer we'll get:
print $buffer ;
// Result:
// myObject
// translateX

Note: Because we used the "." as the splitter, it is now gone from any return strings.

Besides just splitting a string up into different parts, tokenize will also return the number of parts your string was split up into. This can be useful for many reasons as well. Let's say you have a string that looks like this: "myObject,myAttribute,myValue,myMultiplier,myComment". This could be a comma-separated text file you're reading from, or data from a database table. So now for whatever reason let's say we want to know how many comma-separated fields are in this line of text. We can use tokenize for that as well.

// This is the original string
string $myLine = "myObject,myAttribute,myValue,myMultiplier,myComment" ;

// Tokenize it, but save the return of tokenize into an INT variable
string $buffer[] ;
int $numTokens = `tokenize $myLine "," $buffer` ;

print $numTokens ;
// Result: 5

print $buffer ;
// Result:
// myObject
// myAttribute
// myValue
// myMultiplier
// myComment

Now we have both our tokens saved into $buffer and the number of tokens saved into $numTokens. Now that you've got your 5 fields into your $buffer array, you can now define them properly.

// Define Vars
string $object = $buffer[0] ;
string $attribute = $buffer[1] ;
string $value = $buffer[2] ;
string $multiplier = $buffer[3] ;
string $comment = $buffer[4] ;

Note: Remember MEL arrays are "zero-based" so the first index of $buffer is going to be zero.

You may notice that I've defined $value and $multiplier as strings in the above example. Since they are coming from a comma-separated string and then tokenized into a string array they are technically strings. However, since they are most likely floats I can define them as such when I take them out of $buffer. You will get a Warning in Maya when you do this, but it won't stop your script. Same example but with redefined vars below:

// Define Vars, But Assign To Float
string $object = $buffer[0] ;
string $attribute = $buffer[1] ;
float $value = $buffer[2] ;
float $multiplier = $buffer[3] ;
string $comment = $buffer[4] ;

Now we've got five values that we took from our comma-separated text line, all in their own variables with no commas. Very useful! Now, what if we need to save this data out again? How do you form a line again with all these variables? The practical way would be to do this:

// Redefine CSV String
string $myNewLine = ($object+","+$attribute+","+$value+","+$multiplier+","+$comment) ;

This will put all your variables into a new, single string variable. But, if you've done this sort of thing you may have noticed that this will produce an error in MEL, because we're attempting to concatenate two different types of variables a string. In MEL, we can't combine floats and strings together into a string. (Thank you Python!) So, the alternative is to just use our original string array from your tokenize, along with the MEL command: stringArrayToString.

// Redefine CSV String
string $newLine = stringArrayToString($buffer, ",") ;

That will reassemble our string array into a single line again, and use the comma as the splitter. You can use anything you want as a splitter as long as it's a valid character.

Play around with tokenize a bit and see what you can come up with. It's one of the MEL commands I use the most and getting comfortable with how it works and how to use it will improve your scripting a lot!

Looking for more tutorials? Check out Script Swell's Technical Artist Tutorials page.

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