In this tutorial I will use 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 oppinion, 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.

  1. Create a pCube (polygon cube ) and name it something clever ( or don't bother to rename it at all )
  2. 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.

 
 

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
"<<Move" button to make it keyable or the "Move>>"
button to make it non-keyable.

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 diretly in the channelBox.

You can also use the right mouse button with the
attribute selected to hide the attribute and other
simular 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".

 

 
 

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.

 
 

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 har 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.

 
 

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.

Hit "key"

Now we have done it basicly. 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.

 

 

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
translateZ-values.

 

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 favourite 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..

( Right-click, save target as )

 

 
 

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 definetely 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 timeconsuming 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_base
index_middle
index_top
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 startingpoint here or create your
own hand. Maybe you allready have one laying around:

( Right-click, save target as )

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 seperately
  • 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.

 

 
 

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 desimals.
    E.g. 14

    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. Usefull 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" , rightclick
the attribute and lock it. This attribute will only work as a seperator. 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 seperator 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 anyways.
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 simular
driven key setup at both fingers. I didn't bother about the min and max values because I can edit those
with the "Edit Atrribute" 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".

 



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 withthis 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.

indexCurl -10

base 16.381
middle 15.998
top 22.056

indexCurl 10

base -110.892
middle -108.836
top -81.881

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 analyse 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 editchart.

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 atribute, 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 )

( Right-click, save target as )

 

Martin

 
 

The content of this tutorial is copyrighted by law.
Reproduction of the content without permission
will result in legal prosecution.

www.final3.com © 2005