Are relative keying sets (that work on active armature) possible?

Hello all,

I’m working on a short animation with a couple characters whose rigging is identical. I’m trying to use the keying sets feature, but I’ve run across a question. Are keying sets necessarily specific to a particular object? That is, if I want to have a keying set that I use to animate the character’s, do I need to create a separate keying set for each character, or can I create a “relative” keying set that acts upon the active/selected armature?

FYI: I have read Aligorith’s blog post.

Thanks - Andrew

Hi,

Short answer:
“Relative” Keying Sets can only really be created using Python. Check out “keyingsets_builtin.py” for examples how Loc/Rot/etc. and friends are constructed.

Long answer:
I experimented in the past with the idea that relative keying sets could simply be Keying Sets where you’d specify them similarly to “Absolute” Keying Sets, except that you’d leave placeholder “templates” where information should be taken from context (i.e. selected stuff). However, this approach turned out to be overly complicated, lacking flexibility and potentially being quite confusing. For this reason, the decision was made to lump all of these into a system where special Python classes would generate absolute keyingset data on the fly based on context.

Hopefully that helps.

1 Like

That does help, thanks. Actually, I found your tutorial on coding builtin keying sets yesterday and coded up the solution to my problem that way. But it’s nice to know that I wasn’t missing a simpler solution to the problem. Love New Zealand, btw. Spent three of the best weeks of my life traveling around the south island.

For posterity, here’s the python code I used to solve this problem. It basically allows me to have a custom keying set to animate different characters, assuming the bone names are the same (rather than having a different keying set for each character). Only location and rotation are keyed. The code would be fairly easy to customize: just change the names of the bones in the “bones_rotation” and “bones_location” sets to tell the script which bones to key for which properties.

class BUILTIN_KSI_AnimStickMan(bpy.types.KeyingSetInfo):
    
    # this defines how the keying set will appear in the keyingset menu at the bottom of the 3-d window
    bl_label = "AnimStickMan"
    
    # Keyingset options
    bl_options = {'INSERTKEY_XYZ_TO_RGB'}
    
    # Sets that determine what properties (location and rotation) are keyframed for what bones
    bones_rotation = {"UpperSpine", "Toe.r", "Toe.l", "Hand.r", "Hand.l", "LowerSpine", "FootIK.r", "FootIK.l"}
    bones_location = {"LowerSpine", "FootIK.r", "FootIK.l", "ArmIK.l", "ArmIK.r", "PoleTargetArm.l", "PoleTargetArm.r", "HeadTarget", "KneePoleTarget.l", "KneePoleTarget.r"}
    
    # this is the union of the two sets, used in the iterator function to iterate through each of the bones
    defined_bones = bones_rotation | bones_location
    
    # poll     
    def poll(ksi, context):
        ob = context.active_object
        if ob:
            return ob.mode == 'POSE'
        else:
            return False
            
    #iterator
    def iterator(ksi, context, ks):
        # get the active object from the context and store it in a convience variable
        ob = context.active_object
        # reality check to make sure the active object is an armature in pose mode
        if ob and ob.mode == 'POSE':
            # go through all of the defined bones and call the generate functionon them
            for boneName in BUILTIN_KSI_AnimStickMan.defined_bones:
                # make sure the bone is defined in the armature
                if (boneName in ob.pose.bones):
                    ksi.generate(context, ks, ob.pose.bones[boneName])
    
    # generate - adds the paths to the keyframed properties to the keying set
    def generate(ksi, context, ks, bone):
        # get id-block and path info
        id_block, base_path, grouping = keyingsets_utils.get_transform_generators_base_info(bone)
        # deal with the rotation keys
        if (bone.name in BUILTIN_KSI_AnimStickMan.bones_rotation):
            keyingsets_utils.RKS_GEN_rotation(ksi, context, ks, bone)
        # deal with the location keys
        if (bone.name in BUILTIN_KSI_AnimStickMan.bones_location):
            keyingsets_utils.RKS_GEN_location(ksi, context, ks, bone)