Using Driven Keys to create a handController
This task is not very complicated, but it's a tool in Maya you DEFINITIVELY should not miss! Seriously! You have probably downloaded several free rigs on the Internet and all of them have controls controlling other controls. Usually NURBS-curves or locators are used, but you can use just about anything as controllers. Whatever you choose to use, you want the user to be able to handle the rig without difficulties. Animators do not want to manipulate joints. They want controllers to drag around in the viewport. Actually, they usually don't care much about whats beneath the surface at all. They won't relate to it when animating. Make sure you have total control and avoid using floatSliders. About the sliders: This is a personal opinion, but using floatSliders make is so much harder for the animator to get accurate results. This is very easy to achieve using the channelBox. The channelBox is comfortable to work with because you can type in numbers directly, select attributes and use the MMB (middle mouse button) to drag values and while holding Ctrl while dragging you can set the value divided by five.
Let's get familiar with the channelControl then
Create a pCube (polygon cube) and name it something clever (or don't bother to rename it at all)
Open the channelControl (Window > General Editors > Channel Control)
As usual numbered images are clickable for larger view. Some other images are also clickable and if they are I will write a little note next to it.
1 - Get familiar with the channelControl. By default Maya only shows rotate, translate, scale and visibility. This doesn't mean that there are no other attributes, they're just hidden. You can choose to add these hidden attributes to your objects using the channelControl. In Maya 7.0 you can also choose to display these attributes as keyable or non-keyable.
Say you want to show the attribute "rotatePivotTranslateY" in pSomethingClever's channel-Box. Simply scroll down and find it, then you click the "<
You can also hide rotate, translate, scale or visibility. Just choose the ones you want to hide and click "Move>>". You have now set the selected attribute to "Non-keyable hidden" .If you hid scaleY, this will still be affected if you press "s" to set key after using the scaleTool directly. However you will not be able to set a key on this attribute directly in the channelBox.
You can also use the right mouse button with the attribute selected to hide the attribute and other similar options you should look into.
Before we go any further I'd like to go through how driven keys work. The secret lies in the name really. An attribute will control another one based on keyed positions.
Let's do an example together and I'll walk you through the steps. We're going to let the translate of a cube control the rotate of a cone.
1. create a pCube and a pCone and rename the cube "pCubeDriver" and the cone "pConeDriven".
2. Open the "Set Driven Key Window" (Animate > Set Driven Key > Set) Make sure you are in the animation menu. (F2) You will not find the animation drop-down menu if you are in another mode.
The Set Driven Key Window should now be opened.
3. Select pCubeDriver and Click "Load Driver". Then select pConeDriven and click "Load Driven".
2 - Now that we have them both loaded in the "Set Driven Key" window, we can go to work.
I want the cube to translate from translateZ = -10 to translateZ = 10 and I want the cone to rotate from rotateZ = -90 to rotateZ = 90.
When the cube is in origo ( translateZ = 0 ) I also want the cone to stay still. Therefore we need a key to determine the neutral position.
Select pCubeDriver and its translateZ (inside the "Set Driven Key" Window ) Click image below for explaination: and hit the "key" button.
3 - Notice that the pConeDriven.rotateZ attribute in the channelBox has turned red. This indicates that this attribute has been keyed. Maya uses colorCodes to indicate different things. An expression will go purple and if your attribute has multiple connections it will turn yellow.
OK, we have set the neutral position now. Let's set the other two.
Select pCubeDriver and set its translateZ to -10, select pConeDriven and set its rotateZ to -90. (Even though the attribute is keyed earlier doesn't mean we can't set other values here. Since the pCubeDriver.translateZ has changed we can set a new value and therefore get an animation here. If pCubeDriver.translateZ was still at 0 we would have overwritten the neutral position of the cone to -90) If you want to test your driven keys now simply drag the cube between translateZ 0 and translateZ -10
You should see the cone rotate.
4 - Now we have to set a key at pCube.translateZ 10 to complete the task. Select the cube and set the translateZ value to 10. Select the cone and set the rotateZ value to 90.
Now we have done it basically. If you drag the cube back and forth you will see the cone rotating. But you'll also notice that if you drag it further than -10 or 10 nothing happens to the cone. There's no point in letting the animators be able to drag it further.
Select the cube and press "Ctrl+a" to open the attributeEditor. With the pCubeDriver-Tab selected scroll down to Limit Information and open the translate frame. Here you set the Trans Limit Z to -10 for Min and 10 for Max. Now you won't be able to drag it any further than the values we just set.
Scary scenario!!! The Animation Supervisor comes in to tell you that the animators want to have the cone to have a maximum rotation when the cube is at -5 and +5. You might be thinking.... "Maaan, now I have to do it all over again!" But fear not.
5 - When you animate something a node is created holding an animationCurve for that movement. If you open the hyperGraph you can see how your scene elements are connected. (Window > Hypergraph)
Select the cube and click this icon to see the input-and output connections.
Select the pConeDriven.translateZ (animCurveUA) and open its attributeEditor (Ctrl+a remember?)
Under the Anim Curve Attributes frame you can replace the values that are allready listed there. I changed mine to five in this image. Since this is a curve, we can actually edit this in the graphEditor too. With the node selected open the graphEditor (Window > Animation Editors > Graph Editor) Select input and start tweeking. Here you can put some ease-in and ease- out if you want a smoother transition or create a halt at frame 0 etc. etc. It's highly tweekable.
p.s. Don't forget to set new limits to the cube's
If you want to play around with the file I created for this first part of this tutorial you can download the file here: I have supplied all my files in *.ma (Maya ASCII) so if you wish to make the files backwards compatible simply open it in your favorite textEditor and replace all the "7"'s with "6", or the version number for the application you are using, at the top of the document.
To download final3_drivenKeysCubeCone.ma use this link
Since I'm a MEL-junkie I'd like to take this tutorial a bit further. What if the scary scenario above was a request for a tiny change in a huge rig that would hold you at work for so long that you would definitely get in a fight with your girlfriend because you were late again...? Unwanted result! Don't you think it's possible to just copy the action from one driven key to another? Let's say you have made a rig for a index finger. Do you have to go through the same time consuming keying to get the same result on the other fingers? Certainly not. Because every action Maya does are visible for you in the scriptEditor you are able to modify some commands to avoid the fight with your girlfriend :) Let's go through an example...
I have created a simple hand-rig and renamed all the joints to appropriate names. e.g. the index finger is named like this:
index_tip (this one will never be animated because it is the outermost joint where the fingernail would be.)
I also added a simple template geometry for the two fingers I want to use as an example for this tutorial. If you want to try and follow the tutorial you can download the file I use as a starting point here or create your own hand. Maybe you already have one laying around:
To download final3_drivenKeysHandStartingPoint.ma use this link.
The reason I want to rename the joints should be obvious. It's not impossible to work with joint1, joint2 etc, but it's more pleasant to work with logical names, especially when working with MEL. Usually you will find these options in a handRig:
- Curling all the fingers to shape a grip
- Curling joints separately
- Spread the fingers
- Thumb needs an additional control besides curl.
In this example I'm going to rig the index finger and then copy/ edit the commands I used to rig the middle finger too. OK, let's go!
Select the handControl. In the example above we used pCubeDriver.translateZ to control the pConeDriven.rotateZ. In this example we're going to create new attributes with custom names and values to control the fingers.
6 - To add your custom attributes, open the "Add Attribute" Window. Let's take a look at this window and go through the settings.
Attribute Name: write desired name in this textfield. Note that if you write "/indexBase" Maya will display Index Base in the channelBox. However if you want to use the attribute in MEL you'll have to write "nHandControl.indexBase". If you can't remember what you called an attribute simply right-click it and choose Edit Attribute. The attributes for this control will be listed as they were originally typed in.
Data type: A vector is consisting of three floating point values.
An integer is a number with no decimals.
A string can be a collection of symbols from 1-9, A-z and special characters.
A Float is a number with desimals. E.g. 1.2577
A boolean is an on/off attribute.
0 = off and 1= on.
An Enum accepts selections from an "enumerated" or drop-down list. Useful for selecting different subdivisions on a model etc.
- Attribute Type. Don't worry about this one. We will use Scalar. Per Particle and Add Initial State are for particles.
- Numeric Attribute Properties: Here you can add items for your drop-down list and rename them.
OK. Now select nHandControl while you have the window open. Name the new attribute "curl", choose boolean and click "add". Notice the new attribute in the channelBox called "Curl". Change the value to "1" , right click the attribute and lock it. This attribute will only work as a separator. It doesn't look too good so you should experiment with other attributes. "_curl_" with a value of 0 and the data type integer for instance. An emum attribute with an enum name "section" looks good when locked. Note that if you wish to delete an attribute you have to unlock it first. I'll stick with this separator for this experiment.
Add a new attribute called "/index", Date Type "float" and give it a min value of "-10" and a max value of "10" . Set the default to "0". Click "add" . Now you should have two attributes in your channelBox
We don't really need visibility there because that will probably be controlled by another controller anyway's. Right-click it and choose "Hide Selected".
Add a new attribute called "middle" with the Data Type "Float" and hit "OK". Now we have what we need to go through the MEL example where I just edit the commands Maya prints in the scriptEditor to create a similar driven key setup at both fingers. I didn't bother about the min and max values because I can edit those with the "Edit Attribute" window later if I want to.
It's time to dig into the MEL part. Open the scriptEditor by clicking the icon all the way down to the right in the Maya User Interface or by choosing "Window > General Editors > Script Editor..."
By default Maya will not echo all the commands that are running in the background to keep the scriptEditor clean. However, now we really want it to echo all commands and therefore we choose "Script > Echo All Commands".
7 - Open the "Set Driven Key" Window and load "nHandControl" as Driver. Now select "jIndex_base", "jIndex_middle", "jIndexTop" and click "Load Driven". That's right. You can add multiple items when you're working with "Set Driven Key". It saves us some time because I want the attribute called "/index" to control all three joints and form a grip with the indexfinger.
It's from this point on we want to "record" what Maya does. Open the scriptEditor if you have closed it and go to "Edit > Clear History".We are going to set the neutral pose now where everything has a value of "0".
Select "nHandControl" and its attribute "Index", select
"jIndex_base" and its attribute "rotateZ" (Note: This applies to my rig. Your rig could be rigged differently and would possibly require another axis to be rotated) and hit "key". Select "jIndexMiddle", its attribute "rotateZ" and hit "key". Do the same with "jIndex_top".
Now we have keyed three joints in the neutral position and they are now bound to "nHandControl". While you did this, Maya pumped out valuable information for us.
setDrivenKeyframe -cd nHandControl.Index jIndex_base.rotateZ;
setDrivenKeyframe -cd nHandControl.Index jIndex_middle.rotateZ;
setDrivenKeyframe -cd nHandControl.Index jIndex_top.rotateZ;
We are not going to do anything with this now, but keep these lines in the back of your head. Continue setting up the finger. At "nHandControl.index" = -10 rotate the joints a bit backwards and set keys to all of them. WRITE DOWN THE VALUES YOU GET!!! in Notepad or somewhere because these values are important when we want to use MEL later.
A rule of thumb is to go all the way till it looks good and then a bit further so the animators can exaggerate it. These are my settings.
OK, the indexfinger is rigged. Now let's see if we can use the MEL to something useful here. But first a question for you:
- "If you want to edit the rotation value of "jIndex_base" when "handControl.index" has a value of 10, what do you do?
A) I open the "Set Driven Key" Window and key the joint one more time.
B) Easy, I just run one single line of MEL code.
If your answer was A, read on. If your answer was B, well then you already know the easier way to do this :)
Obviously Maya used the command "setDrivenKeyframe" to set Driven Keyframes. I looked it up in the Maya MEL command reference. (help > MEL command reference) and found out that the flags I have to use was -driverValue (-dv) and -value (-v). When you want to check if something works, use some insane values to see the changes. If you wonder if a light is behaving correctly with its intensity 1 boost it up to 100 or more to get a direct feedback. Here I don't have to go crazy to check because it will be very obvious that something changed. I am going to try and edit "jIndex_middle's" value when "nHandControl.index" has a value of "10". I write this line in my scriptEditor and run it:
setDrivenKeyframe -dv 10 -v -25 nHandControl.Index jIndex_middle.rotateZ;
I can see that it works when I slide the nHandControl.index value. And so can you on the image below. Compared to the image above you can clearly see that the angle on jIndex_middle no longer rotate all the -108.836 degrees,but -25 degrees.
Yes! A new era to rigging has begun :) Let's analyze what we just did and use it to rig the middle finger.
setDrivenKeyframe -cd nHandControl.Index jIndex_middle.rotateZ;
This is the sentence originally found in the script Editor.
- "setDrivenKeyframe": Basicly the command that tells us that we are setting a driven key.
- "-cd": Short for currentDriver. What this flag does is to tell Maya that she shall use the first stated object as the driver.
- "nHandControl.Index jIndex_middle.rotateZ": Tells Maya to key the values of these two selected attributes.
But our editline did not look like that. The reason is because I don't want to depend on a selection. That's actually the whole point with this. Therefore I need a way to insert custom values. As you remember, my line looked like this:
setDrivenKeyframe -dv 10 -v -25 nHandControl.Index jIndex_middle.rotateZ;
When I looked up the command in the MEL command reference I noticed that the way you should set this up is setDrivenKeyframe (flags) (objects);
"setDrivenKeyframe": We should know what this does by now.
"-dv": short for driverValue. This is where we set the value of the driver.
"-v": Short for value. This is where we set the value of the driven
"-cd": Short for currentDriver.You state that nHandControl is the current driver.
"nHandControl.Index jIndex_middle.rotateZ": Then we list the driver first and then the driven.
With our clever brains we should be able to understand what to do next. nHandControl still runs the show and our next thing to rig will be the middle finger. The new lines of code will then be:
//This is to set the neutral position
setDrivenKeyframe -dv 0 -v 0 -cd nHandControl.Middle jMiddle_base.rotateZ;
setDrivenKeyframe -dv 0 -v 0 -cd nHandControl.Middle jMiddle_middle.rotateZ;
setDrivenKeyframe -dv 0 -v 0 -cd nHandControl.Middle jMiddle_top.rotateZ;
//This is to set the negative position
setDrivenKeyframe -dv -10-v 16.381 -cd nHandControl.Middle jMiddle_base.rotateZ;
setDrivenKeyframe -dv -10-v 15.998 -cd nHandControl.Middle jMiddle_middle.rotateZ;
setDrivenKeyframe -dv -10 -v 22.056 -cd nHandControl.Middle jMiddle_top.rotateZ;
//And this is to set the positive position (grip)
setDrivenKeyframe -dv 10-v -110.892 -cd nHandControl.Middle jMiddle_base.rotateZ;
setDrivenKeyframe -dv 10 -v -108.836 -cd nHandControl.Middle jMiddle_middle.rotateZ;
setDrivenKeyframe -dv 10 -v -81.881 -cd nHandControl.Middle jMiddle_top.rotateZ;
Obviously you don't need to include the flag -cd when editing, but the rig isn't affected by it anyway. So keep it there to use the script as both a creation and a possible edit chart.
Now, if you're smart you'll gather all these lines for all the fingers and put them in the same MEL file for later editing. Let's come up with a scenario again. Scenarios are fun :) You have rigged a monster with 10.000 fingers.... Of course you are told to correct this. The rotation of all the middle joints are set up at "100" and the animation supervisor wants it to be "130" because the animators don't feel they get freedom to exaggerate as I talked about earlier. Instead of banging your head against the wall you say "Give me three minutes. " What's even more rewarding is the supervisors face when you say a huge change like that will take three minutes. You fire up conText or whatever textEditor you use and replace "100" with "130". Most editors can replace multiple numbers, words etc. etc. with another one. (This will not work if you have all the basejoints at a value of 100 for instance, but since you know that this might happen you coded all the basejoints to 101. Stay ahead of corrections :) ) Then you load the MEL-script into Maya and run it once. Overwrite the file and tell the animators to try it out. They are satisfied and you can go home to your girlfriend while these animators are the ones working overtime with their new rig getting into their own fights when they come home
at 11 pm. :)
Now I'm going to go through one final thing before I let you go. I'm going to add a control for jIndex_top so you can rotate it independently of the curlControl. What this means is that you can use the Index attribute under Curl to curl the indexfinger and then you can tweek the position of the top joint by using this new attribute called indexTop. I'll add a seperator called Additional Curl so you con't lose control.
Since we know how to do this with MEL we don't use the "Set Driven Key" Window anymore. Simply add these lines to your script:
setDrivenKeyframe -dv -10 -v 56 -cd nHandControl.indexTop jIndex_top.rotateZ;
setDrivenKeyframe -dv 0 -v 0 -cd nHandControl.indexTop jIndex_top.rotateZ;
setDrivenKeyframe -dv 10 -v -126 -cd nHandControl.indexTop jIndex_top.rotateZ;
I did this to show you that the jIndex.rotateZ can have multiple inputs. If you select this joint now and look at the attribute, it has turned yellow.
I Actually learned something by writing this tutorial as well. I hope you, the reader, learned something too. I tried to split this tutorial between the very basics of Driven Keys and then to intermediate. If you couldn't keep up with the MEL-part, take a look at this tutorial in a couple of months when you have started learning MEL ( of course, since you know now what tremendous power that lies within MEL )
If something was badly written, if you didn't understand this, if you find some typos or if you feel like giving me any kind of feedback please use the contact form at the top of this site. I appreciate all kinds of feedback.
Oh, and by the way. Here's the finished file if you want to play around with it I didn't set the other joints to have additional curl so if you would like to try it out feel free to wreck the file :) ( Remember to create a backup first of course).
To download final3_drivenKeysHandsFinished.ma use this link