Monday, December 27, 2010

[Animating in 2.5] Getting to grips with Keying Sets

Over the past few months, I've been observing quite a bit of confusion over some aspects of the animation system in 2.5 that's all related to "Keying Sets". These are a rather important new feature aimed at improving the animation workflow, but which many people don't seem to be aware of. So, if you're wondering why you're getting a "weird" error message when trying to insert keyframes, or if you'd just like to learn some new workflow tricks to make animating easier, read on :)


A bit of history first... (2.4x days)
What many may not be aware of, is that you've (assuming you have used the 2.4x series) been using Keying Sets for a lot longer than you know.

2.48 Insert Keyframe Menu - Screenshot from my release notes for this release
(http://www.blender.org/development/release-logs/blender-248/animation-tools/)
Back in 2.48, I did a round of animation system related cleanups, some of which included some cleanups to the keyframing code. Before this point, each menu entry in the IKEY menu corresponded to one of a series of "if-statements" calling "insertkey()" per channel of animation, in one nasty blob of code.

So, during the 2.48 cleanup, I refactored this blob of monolithic code into the first version of Keying Sets: a primitive hard-coded system that just stored a small (32 items at most) list of the "adrcodes" that would be keyframed together.
"adrcodes" were numbers that IPO-Curves used to identify the property they were allowed to affect. A limited number were hardcoded into Blender, but adding new adrcodes for "new" properties or just for existing ones that weren't already covered was a lot of pain, requiring adding duplciated defines and settings for them in at least 5 places
With this new system in place, I was able to simplify and make more consistent all the code for handling the IKEY menu and keyframing, which still forms the foundation for the keyframing code in 2.5 today.

Therefore, everytime you inserted a keyframe in 2.48 onwards, you were really using a Keying Set. The IKEY menu was simply a list of all the Keying Sets available in the given context.

However, despite these changes, keyframing in 2.4x was still not really "good enough". Primarily, the limitations of the nearly 15-year-old-dinosaur, the "adrcode" system leading to few properties being able to be keyframed, only being able to keyframe sets of properties decided at compile time and in the same 'block', and having to select the Keying Set to use everytime you went to insert a keyframe.

Animato and Keying Sets - A fresh start
As part of the 2.5 project, a new "Data API" (later known as "RNA" to complement our "DNA" file-format) was created. This acts as a layer between data (properties) stored in DNA, and all the various places that you as a user can try to access/change those properties goes through this layer. It provides information about the naming of the properties, the ranges, types, and assorted validation stuff to make sure that you can't corrupt things easily. Systems using this layer include: UI controls/widgets, Python API, and the Animation System. So Animato (Animation System) effectively uses RNA as its data-access core.

The most important RNA feature used here are the "data paths" - i.e. chains of property identifiers used to access a property given a starting ID-block. If you've done any work with the new Python API in 2.5, you should already know what these should look like: just strip off the "bpy.data.objects["ObjectName"]." (the last part here could also be any other ID-blocktype, such as lamps, worlds, armatures, etc., but I've used objects here since it's the most frequently encountered one) or "bpy.context.active_object." parts from the front of those lines of code you'd use there.

Another important thing I should point out about RNA is about the distinction between "array" and standard properties. Basically, an "array" is like a property that stores multiple values as sub-properties. Another way of looking at it is by saying that an array is like a trough with a name (property identifier) and inside this trough you have some buckets holding different coloured flowers. You refer to the flowers by saying "I want the flower in the 2nd (or ith) bucket". Examples of "array" properties in Blender include all the transforms (Location, Rotation, Scale), with say, X-Location being referred to as "location[0]" or "location[x]" or "location.x".

At the most basic level, Keying Sets are effectively a way of specifying a set of such paths, along with the ID-blocks they should be branched off from, and any options that should be taken into account when using these to add new keyframes.

Types of Keying Sets
There are basically two types of Keying Set in Blender: "Builtin" and "Absolute".

Builtin are the ones that are always available (context permitting) in Blender. They are the (familiar) ones that show up in the IKEY menu by default - "Location", "Rotation", "Scaling", and friends. All you generally need to know about these are that they are defined using in Python so that they can check the context to see what properties they should act on. This means that you CAN'T add/remove properties from them yourself unless you edit the Python code which determines what they use. If you're curious to add a few more 'builtins' that you commonly like to use, you can find these under scripts/keyingsets/ in your install directory. Be aware though that the attempts at making these definitions quite "modular" may initially be a little confusing for novice/beginner Python programmers, though they should still be quite easy to grasp. The topic of setting these up shall be left as an exercise to the reader and/or a future post :)

Absolute are the ones that you should be most interested in, as they are the "user-defined" Keying Sets, and are stored per Scene (that they are defined for). By setting up and using these carefully, you can improve your workflow quite a bit. Used appropriately, you can insert keyframes for a whole bunch of related properties with the touch of a key (or single click if you like), saving frustration from forgetting to key one of a bunch of properties and saving time jumping around keying multiple things separately. This has significant benefits, especially for the modern character animator working in the standard pose-to-pose full-pose blocking method, where keying every single control on every key-pose at once is the m├ętodo comodo.

Defining Keying Sets - Multiple ways to skin the hungry cat
Method 1: RMB Context Menu
For most properties, the easiest way to add a property to a Keying Set is to use the RMB context menu on properties, from which you can also add drivers or keyframes, and choosing "Add to Keying Set" (or in the case of array properties, "Add All to Keying Set"). This is also the way most people remember.


Method 2: Hotkeys
I should also point out here that there is a shortcut available.
1) Hover over a property
2) KKEY to add property to Keying Set, Alt-KKEY to remove.
From reading of some of the confusion people are having, accidental invocation of this (without being aware of its existence) is probably a cause for a number of cases of "can't insert keyframes".

While I'm talking of property editing shortcuts, IKEY and Alt-IKEY perform similar functions for Keyframes, while DKEY and Alt-DKEY perform similar functions for Drivers, all in the same way as above. Also, did you know that you can Copy/Paste values from property buttons by just hovering over them instead of actually needing to click. One last little tip is 0-KEY can be used to quickly reset values to their "default values", although for most properties, these defaults haven't been properly defined in RNA yet.

Method 3: Datablocks viewer
Now, although for most properties this will work well enough, sometimes there is stuff that you can't get to that easily using this method. For those tough cases, you may want to consider using the Datablocks view in the Outliner instead. I've mentioned this method in a few of the other FAQ's already, but I might as well mention it again here for completeness.

1) Go to an Outliner Editor (top right editor in default window layout), and change the mode (combo-box on header) to 'Datablocks'.
2) Go through the list, and expand the entry of the ID-block type list (i.e. Objects, Scenes, Worlds, Materials, etc.) where the data you want to animate is.
3) Find the entry for the ID-block you're interested in within this sub-tree.
4) Go through the list, opening up entries with + signs beside them (as appropriate), progressing further down the tree until you find a property that you wish to affect.
5) Click on some empty space on the same row as the property. This row should now be highlighted in light-grey/blue.

6) Just like for normal properties, KKEY to add this property to active Keying Set, or Alt-KKEY to remove. (For good measure, try to not have the mouse hovering over the values column when doing this, otherwise you might get the property added with one of those paths being instead, which is a key reason for doing things this way).

Method 4: Scene buttons
Yes, there is a fourth(!) method. Incidentally, this method is also how you edit the settings of a (Absolute) Keying Set, and can manage the properties it includes. In essence, this is practically similar to the previous method in that you'll be constructing the path yourself. The only difference though, is just that there isn't really a visual representation of the paths for you to choose from and explore.

Keying Set Settings
In the Properties Editor, you can find the settings for editing the user-defined "Absolute" Keying Sets for the Scene under Scene Tab. These can be seen in the following screenshot:

Panel 1: "Keying Sets"
This panel shows the Absolute Keying Sets available in the current Scene. Using the +/- buttons beside the list, you can add/remove Keying Sets.

The buttons below this list all operate on the active Keying Set (which will usually, but not always be the selected item in the list. More on this later). Here is a brief description of what they do:
  • Name: self explanatory, this is the name we use to identify the Keying Set by
  • Export to File: this operator writes a Python script file with commands which can recreate this Keying Set in another file. This is particularly useful for riggers (or even animators) to set up some Keying Sets for some characters they're working on and then import these Keying Sets into new shot files as necessary. It's also a nice demo of the Keying Sets API, in case you were wondering how it worked.
  • Keyframing Settings: these are flags which define how keyframes for all properties in the Keying Set will be added. They are non-exclusive, so you can have whatever combination of them that you like
    • Insert Keyframes - Only Needed: this option results in a heuristic being applied when adding keyframes so that the number of duplicate keyframes inserted is reduced, thus keeping the F-Curves cleaner and lighter
    • Insert Keyframes - Visual: this option only applies for transformation keyframing. Instead of just reading off the local transform values (i.e. those set by transforming the object/bone yourself), it also takes the effects of constraints into account.
    • F-Curve Colors - XYZ to RGB: when F-Curves need to be created by this Keying Set (the keyframes have to go somewhere, right?) they will be coloured so that XYZ transforms will correspond to Red,Green,Blue colours (i.e. X-Axis = Red, etc.) instead of the default "rainbow" set of colours. With the current defaults though, this option is less relevant, though personally I still prefer the rainbow set over everything being RGB...
Panel 2: Active Keying Set
This panel allows editing the set of properties that the Keying Set in the panel above deals with. Just like the panel above, the +/- allowing adding/remove "property targets" for the Keying Set to manage.

Following the familiar drill, let's just go over what each button under the list is for:
  • ID-Block selector: recall how I talked earlier about ID-blocks and paths being relative to them? Well, this selector allows you to select the ID-block that gets used.
    • The dark dropdown box allows you to choose the type of ID block (i.e. Object, Mesh, Lamp, Camera, etc.), filtering the list of ID-blocks you need to search through
    • The box beside this on the other hand allows you to select a specific ID-block of that type
  • Data Path: see back up above for a reminder of what these are. This defines how to get to the property from the ID-block chosen above.
  • Array Target: check back above if you've forgotten what "arrays" were. The settings in this group define how "arrays" should be handled if the property you've chosen is an array:
  • Entire Array On
    Entire Array Off
    • Entire Array: When enabled (default), every value in the array will be keyframed. This is useful for keying all the components of some transform (i.e. Location X+Y+Z) or Color (Diffuse R+G+B) all at once instead of having to define separate "property targets" for each component.
    • RNA Array Index: When Entire Array is disabled, this setting becomes visible. What this does is it allows you to select the particular component that you'd like to include. For example, if I only wanted to include the Y Location of some Object, then I'd set this to 1 (NOTE: array indices are 0-based, so X=0, Y=1, Z=2 OR R=0, G=1, B=2, etc.)
  • F-Curve Grouping: this is perhaps another aspect that needs quite a bit of explaining as it seems to be one of the things that has been confusing people. See below for the discussion on this, as I don't think it'll fit in here :)
  • Keyframing Settings: these are the same as for the first panel, except that this time they only apply to the specific property. These are additive over the Keying Set's default, so for example if the Keying Set had "Visual" enabled, the Visual setting here is useless, but if it wasn't enabled, then enabling the setting here would make just this property to get Visual Keying.

The Deal with F-Curve Grouping
As with the "F-Curve Colors" setting, the way that a F-Curve is "grouped" is only relevant when the F-Curve needs to be created so that the keyframes will have somewhere to go (i.e. when such an F-Curve doesn't already exist).

Firstly, when I refer to "grouping" here, I'm referring to those "green" channels in the Animation Editors. These are generic "F-Curve Groups" NOT specifically "bone channels" or "bone groups" (although they can be used for that purpose). For example:
(group has been highlighted with a red box. Note that the group name is controlled by the Keying Set, NOT by any other measure. Also note that apart from the initial creation of the groups and channels, the Keying Sets do NOT place restrictions on your ability to edit them as Maya does).

So, what are the grouping methods provided by the Keying Sets?
  • Keying Set Name: this method is the default for newly created property targets in Absolute Keying Sets, as hopefully your Keying Set already has a meaningful name which relates to why these properties are getting keyed together, so grouping them this way just enhances their purpose.
  • Named: this method allows you to specify a custom name. The greatest use of this is if you have multiple bones to key within a single Keying Set, but you still want the F-Curves to be grouped in smaller groups (i.e. by bone name, by bone group, or some other means)
  • None: it is also possible that maybe you don't want the F-Curves grouped at all. Although this is not that great if you have a lot of channels, it may be ok if you just have one or two and/or are mixing Keying Set keying with direct hover-over button keying.

Ahh, but the eagle-eyed out they may notice that this does not seem to be the full story. I include an edited copy of a response to a bug report I recently wrote explaining this situation:
Keyframing via operators (i.e. IKEY menu in 3D-View, timeline header, etc.) uses Keying Sets. [The following naming defaults ONLY apply to the builtin Keying Sets which appear in this menu at startup.]

Inserting keyframes via buttons (i.e. RMB menu over any button, or IKEY over any button) bypasses the Keying Sets as there there is only a single property that we already know how to access. However, there isn't any other information other than where we want them inserted.

Now, the default grouping methods for [Builtin] Keying Sets have been chosen so that if you just pick up Blender and animate, your F-Curves will be grouped so that they can be easily found instead of being just one single long list:
- Non-bone channels will just get the name of the Keying Set by default, as this means that if you just added a set of properties to a Keying Set (i.e. Material Colour + Object Scale), then you could easily find this grouping of related settings by just looking out for the F-Curves in the group with a matching name
- Bone channels are grouped this way by default so that you can easily find all the F-Curves associated with a bone. True, this means that by default we lose the Bone Groups <-> Action Group association, but this is under the assumption that you're more likely to want to finely-edit animation for single bone than a group of them.

However, as I've already mentioned, when bypassing KeyingSets, we don't know anything about these grouping methods, so they are just ignored.

Using Keying Sets
Now that we know how to define and edit Keying Sets, how do we work with Keying Sets while animating?

Hit the ground walking
If you're just doing simple animation, you could just go about it the same way as you did in 2.4x. That is, pose your objects/characters, select the things to keyframe, and then IKEY to bring up the menu with built-in Keying Sets and chose the one to use for the job at hand. This worked before and continues to work, but this is not the most efficient way to be working.

Setting the Active Keying Set
By setting an "Active Keying Set", a lot of keyframing operations become a lot easier and more controllable/reliable.

The easiest way to do this is to use the controls in the TimeLine header, as can be seen in the following screenshot:
1) Click on the text-field (i.e. the long widget with the key icon)
2) You should now be presented with a popup search menu with the names of Builtin Keying Sets as well as any you have defined in the Scene, as shown below
3) Now, you can either start typing and press enter when you're done (the list will be filtered to only include matching names as you type. Also backspace works normally if you make a mistake while typing), or simply click on any name in this list.
4) Say I clicked on 'LocRotScale' in the previous step. Now I have set the active Keying Set to LocRotScale, and the widgets in the TimeLine header look like:
With this set, I can now go ahead and animate as usual by pressing the IKEY to insert keyframes, but now I don't have the menu popping up everytime asking me what Keying Set I'd like to use as I've already told Blender that.

Changing the Active Keying Set
Now, let's say that I now want to animate something else but keying only Location.

Let's first do this the long way (hint for skim readers + web crawlers: this is also known as "clearing active Keying Set"):
1) Click on the text-field again as before. Depending on the way that you set the Active Keying Set last time (i.e. whether you typed in a name, or just clicked on one), the list may well have just a single item in it, like this:
2) Never fear! No matter how you set the active Keying Set before, the way to clear the Active Keying Set is just to hold down the Backspace key in the text field disappears
3) Now for the crucial step: press Enter to clear the text field. If you just click outside, the menu will be dismissed and treated as cancelled, so the old values will still persist.
(4) if you now want to set another active Keying Set, you can now perform the normal steps again.

You don't always have to clear the old one before setting a new one though. In the above steps, after performing step 2 (pressing backspace), you can go straight into setting the new active Keying Set without having to first set the field to empty before setting another value.

Another way to set the Active Keying Set
In the 3D-View, it is also possible to set the Active Keying Set using a hotkey combination. If you press Ctrl-Shift-Alt-IKEY you will be presented with a menu, much like the standard IKEY menu, but which will only change the Active Keying Set.

While I thought it might be handy to have when I initially added it, on second thought, this is probably a bit too obscure/indirect anyway to be of much use. But at least now that I've documented it, maybe people might now find this indispensable ;)

Other cool things you can do with an Active Keying Set set
In the screenshots above, you may have noticed two buttons beside the field for the active Keying Set in the TimeLine header. These are for adding and removing keyframes using the Active Keying Set respectively.

Auto Keyframing and Active Keying Sets
With just a bit of setup, you can make your animating workflow very smooth, though perhaps this approach is only preferred by some more than others.

Anyways, if you go to the User Preferences -- Editing -- Auto Keyframing settings, you'll see an option labelled "Only Insert for Keying Set", as highlighted in the screenshot below:
If you enable this and set an Active Keying Set, all tools which use Auto Keyframing (Transform tools, Clear Transforms, Paste Pose, etc.) will all just ask the Active Keying Set to insert keyframes on its behalf, instead of using the tools choosing their own builtin Keying Sets as they deem necessary. The key benefit of this is if you're trying to ensure that everytime you've got keyframes being inserted you will have the entire pose blocked (in with keyframes), then this is done automatically for you, so that you don't have to worry about remembering to key all manually or in a separate step.

Troubleshooting Keying Sets
I thought I'd just make a brief mention of some how to interpret some of the error messages that you might get while working with Keying Sets or keyframing in general.

No suitable context info for Keying Set
This error occurs when either:
  1. The Keying Set requires that some specific type of data is selected (i.e. all builtin Keying Sets require that you have some selected object/bone)
  2. When using the "Available" builtin Keying Set, and the object that you're trying to keyframe doesn't already have any keyframes/F-Curves, this error will be shown as it there are no existing keyframes/F-Curve on the selected object(s) to insert keyframes on
Keying Set failed to insert any keyframes
This error occurs when:
  1. The data-path and/or array index cannot be resolved correctly
    • There is some missing code in Blender (RNA to be precise) for defining the path to get to the data containing the property from the ID-block. If you find one of these cases, please file a bug report labelled "Missing RNA Path Defines for "
    • You made a typo (if you defined the paths by hand). Double check the defines in your Keying Set :)
  2. The F-Curve (or its group) are locked, so not keyframes can be added as that would mean modifying the locked F-Curves

12 comments:

  1. Really useful explanation of Keying Set's hopefully everyone doing animation reads it!

    ReplyDelete
  2. Finally i know how to use this tool. Thank you so much Aligorith..

    I have a question though, based on my experience with another software. Is it possible to just save a selection of bones, and then we can recall the selection again to make a key on it and we can decided whether we want to just key the loc, rot, scale, or everything later. From my perspective, to use a keyingset, i have to select one bone, and then hover my mouse cursor to location and hit KKey, hover to Rotation and hit KKey and hover to scale and hit KKEy, select another bone and so on and so on. This i think is too much time consuming, especially if animator (like my self) just want to animate the simplest thing on bones, like loc, rot and scale.

    I think, the Keyingset is very useful for one case, but perhaps not on another.

    Thanks again ^_^

    ReplyDelete
  3. Johantri - I think you may have the keys mixed up - press IKEY to add a keyframe for the property, press KKey to add the property to the keyingset.

    I think what you are asking is how it works - in the timeline window if you select a keyingset (see above under "Using Keying Sets") then when you press IKEY to insert a keyframe only items in the keying set will be added.

    eg if you select LocRot as the keying set then IKEY will only key the location and rotation of the selected bones.
    If you activate auto keyframing then anytime you move a bone the location and rotation will be keyed for you.

    The bit you may be missing with auto keyframing is to turn on "Only Insert for Keying Set" in the preferences. (See the screen shot just before troubleshooting) This will limit the auto keyframes to the selected keying set.

    Another option is Only Insert Available - this means it will only record keys for existing f-curves. So you need to manually key a value (once) for it to record changes for you.

    ReplyDelete
  4. I think that Johantri does not have things mixed up, but is talking about building useful keying sets...

    ReplyDelete
  5. The 0KEY should clear the active keying set. Would be much easier than click-bsp-enter combo :)

    ReplyDelete
  6. Um, a typo:

    on "Animato and Keying Sets", "(later known as "RNA" to compliment our "DNA" file-format)"

    You mean to say "complement".

    Sorry, I'm an ass for posting this here - Do delete my comment when you're finished with it :)

    Awesome awesome article! Thanks!

    ReplyDelete
  7. Are you okay? Also from Christchurch.

    ReplyDelete
  8. Thankyou for this. I really didn't understand what keying sets were before.

    ReplyDelete
  9. This was really helpful Aligorith - thankyou!

    One comment tho:

    At the minute the only way i have found to import my Keying Sets from other files is by copying the pasting the .py file into Blender's text editor then running the script.

    While its very cool that you can do that, maybe an import button would be easier? it looks like there's a nice space for it just below the 'Export to File' button! :0D

    Thanks again!

    ReplyDelete
  10. is it possible to add a property that is not tied to a specific object, but instead will change the keyed object according to the selection?

    ReplyDelete
  11. widelec: You'd need to write a "builtin" keyingset using Python to do that. See how the default loc/rot/scale ones are done :)

    ReplyDelete
  12. Thank you Joshua, o mighty Guru!

    After reading and trying this out over several nights,
    I get the impression that the following functionality is missing
    [please tell me I’m wrong!]:

    Suppose you have a scene that includes a windmill and some characters,
    and you want to define two shots for that scene:

    1.- An establishing shot, only camera and windmill move.

    2.- Focus on characters, windmill in the background.

    Suppose you’ve done the first animation,
    and you want to perfect it later,
    but right now you feel an urge to focus on the characters.

    Wouldn’t you want to collect the keyframes
    that you’ve done so far, into one keying set,
    attach it to the scene, save it, mute it
    —so that alt-A in the 3D View shows no movement,
    and the Timeline shows no yellow lines—
    and start a new keying set that refers
    only to the characters and to a second camera?

    And when that has been done and tested
    (the windmill in the background doesn’t move at all),
    wouldn’t you want to be able to easily merge
    both sets of keyframes into a third set?

    ReplyDelete