Mocappys

Your Guide to Capturing and Editing Motion

  • MotionBuilder Tutorials
  • Motion Capture Guides
  • Academy
  • Contact
  • About
  • Search Results
You are here: Home / MotionBuilder Tutorials / How to Write a Skeleton Definition File Using Python

How to Write a Skeleton Definition File Using Python

By Mocappy 2 Comments

Table of Contents

Toggle
  • Create a list of Character Definition Slot Property names
  • Create an Ordered Dictionary
  • Convert Ordered Dictionary to ElementTree
  • Make the ElementTree Pretty (XML)
  • Write Skeleton Defintion XML
  • Test with Current Character

The usual way to save a Skeleton Definition XML file is from “Character Controls>Definition>Save Skeleton Definition…” But, what if you’re looking for a programmatic way of doing it using Python – or someone left a comment on a previous post asking how to do it and you can’t resist a python challenge? Well, then you end up with something like this…

Create a list of Character Definition Slot Property names

To start, we need to import a couple of functions to help us do what we need. We’ll need os to create our directory paths, etree to create our xml, dom to make it pretty and OrderedDict to build the xml from.

from pyfbsdk import FBApplication
import os
import xml.etree.ElementTree as etree
import xml.dom.minidom as minidom
from collections import OrderedDict

Create an Ordered Dictionary

Now we can go through all the properties in FBCharacter and find the ones that have “Link” in the name and ignore any that also contain “Game” and “Leaf” as these aren’t used in the Skeleton Definition XML. Then we can use the same property to get the joint name from the “Mapping List” and combine all that information to create an Ordered Dictionary.

Couple of things about this…

  1. First, the “Mapping List” in the Character Definition tab is a python list even though it only ever contains one object, so we need to get the first [0] object in the list.
  2. Second, we need to use an Ordered Dictionary to create the XML. When I tried this with a standard python dictionary, the order is randomised. The problem with this is, if you load the XML file using Character Controls>Definition>Load Skeleton Definition… it fails spectacularly at assigning the correct joints in the correct slots – I’m guessing it’s using the order of items, not their names – if you’re going to use python to populate the “Mapping List”, this won’t be a problem.
def get_character_slotName_jointName_orderedDict(character_object):
    """
    Create character mapping slot name, joint name ordered dictionary
    Must be ordered dictionary to work with Character>Definition>Load Skeleton Definition...
    Returns slot name, joint name ordered dictionary
    """
    # Create empty list for slot name and joint name
    slot_name_joint_name_list = []
    for character_property in character_object.PropertyList:
        if "Link" in character_property.Name\
        and not "Game" in character_property.Name\
        and not "Leaf" in character_property.Name:
            character_slot_obj = character_property
            # Remove 'Link' to get character definition slot name
            slot_name = character_slot_obj.Name.replace('Link', '')
            # Check slot has "Mapping List" object assigned
            if character_slot_obj:
                # slot returns a list of objects, so get first
                joint_name = character_slot_obj[0].Name
            else:
                joint_name = ""
            # Add slot_name and joint_name to list
            slot_name_joint_name_list.append((slot_name, joint_name))
    # Create ordered dict from list
    slot_name_joint_name_ordrd_dict = OrderedDict(slot_name_joint_name_list)
    
    return slot_name_joint_name_ordrd_dict

Convert Ordered Dictionary to ElementTree

Once we have an Ordered Dictionary, we can convert it into an ElementTree ready to create the XML.

def convert_dic_to_etree(ordered_dict):
    """
    Convert ordered_dict to ElementTree
    Use default template naming
    Returns ElementTree object
    """
    # Create root
    config_root = etree.Element('config_root')
    # Add match list subelement to root
    match_list = etree.SubElement(config_root, 'match_list')
    # Add each item in dictionary to mach_list as Subelement   
    for dslot_name, djoint_name in ordered_dict.iteritems():
        etree.SubElement(match_list, "item", key=dslot_name, value=djoint_name)
    
    return config_root

Make the ElementTree Pretty (XML)

Then, we can convert the ElementTree to “Pretty XML” using dom so it looks nice is human readable and has the same formatting as a Skeleton Definition XML created from the Character Controls window. We also need to remove the XML header to make it compatible with “Load Skeleton Definition…”.

def convert_etree_to_pretty_xml(etree_obj):
    """
    Convert ElementTree to pretty xml to match default skelteton template xml format
    returns pretty xml with no header
    """
    # Convert etree to string
    xml_string = minidom.parseString(etree.tostring(etree_obj))
    # Convert string to pretty xml
    xml_pretty = xml_string.toprettyxml()
    # Remove header and whitespace from xml
    xml_with_no_header = xml_pretty.split('?>')[1].strip()

    return xml_with_no_header

Write Skeleton Defintion XML

Finally, we can put everything together and write the XML to the default MotionBuilder “template” folder.

def save_skeleton_definition_file(character_obj, skel_def_file_name):
    """
    Save Skeleton Definition File for character
    Save to Default Template folder
    """
    # Set default template path
    skel_def_template_dir = os.path.join(os.path.expanduser("~"),
                                        "AppData", "Roaming",
                                        "Autodesk",
                                        "HIKCharacterizationTool6",
                                        "template")    
    # Create full XML file path
    skel_def_file_path = os.path.join(skel_def_template_dir, skel_def_file_name)
    # Get Character slotName jointName Ordered Dictionary
    skel_def_dict = get_character_slotName_jointName_orderedDict(character_obj)
    # Convert Dict to ElementTree
    etree_skel_def = convert_dic_to_etree(skel_def_dict)
    # Convert ElementTree to pretty XML
    pretty_xml = convert_etree_to_pretty_xml(etree_skel_def)
    # Write Skeleton Definition XML
    with open(skel_def_file_path, 'w') as xfile:
        xfile.write(pretty_xml)
        xfile.close()
    print "File Saved as:{}".format(skel_def_file_path)

Test with Current Character

All that’s left to do now is get the CurrentCharacter and write a Skeleton Definition XML we’ll use the character’s name as a prefix to help find it later.

current_character  = FBApplication().CurrentCharacter
save_skeleton_definition_file(current_character, current_character.Name + "_template.xml")

Like I said at the start, I do enjoy a bit of python challenge. It’s not the first time I’ve wondered how to do something, and then disappeared down a rabbit hole for hours or days….

Anyway, hope this has answered the question in the comments on the previous post or given you a few ideas for a new tool in MotionBuilder.

Tweet

Filed Under: MotionBuilder Tutorials

« How to Use MotionBuilder Story Tool to Create a Cut-Scene
How to Animate Props in MotionBuilder | Multi-Referential Constraints »

Comments

  1. Jaisurya Chandrasekar says

    August 7, 2024 at 10:41

    What if I already have a skeleton definition in XML, and loading the xml in the current skeleton which I have in the scene. There is a button in motion builder to ‘load skeleton definition’ How can I do it with python?

    Thanks!

    Reply
    • Mocappy says

      August 21, 2024 at 16:33

      I don’t think this button is exposed in python (most aren’t), so you have to use the FBCharacter, etc. to get the same effect. Sorry.

      If you already have the XML, you can convert it to a dictionary and use that, like it do in this tutorial

      Reply

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Search Site

Ready to Dive into MotionBuilder and Start Editing Mocap But Feel Overwhelmed?

edit mocap motionbuilder

Your complete step-by-step guide to creating production ready animations for video games and simulations.
…Even if you’ve never used MotionBuilder.
By the end of this comprehensive, hands-on course, you’ll be creating production-ready animations that blend together seamlessly.
<< Learn More >>


Hi, I’m Simon Kay

My aim for this site is to share everything I’ve learned over the last 20+ years using MotionBuilder to help bring hundreds of characters to life at some of the world’s leading VFX, Video Game and Motion Capture Studios, including DNEG, Sony Interactive, and Centroid Motion Capture.

 

Top Posts:

  • How to Rig a Character for MotionBuilder
  • How to Mocap a Performer using a Vicon System
  • Retargeting Animation In MotionBuilder
  • Complete Guide to Pose in MotionBuilder
  • How to plan a Motion Capture Shoot – Mocap Shot List
  • Using MotionBuilder Story Tool
  • How to Characterize your Character in MotionBuilder
  • How To Create a Walk Cycle in MotionBuilder
  • Creating an In-Place Looping Animation in MotionBuilder
  • How to Retarget Motion Capture in MotionBuilder [video]

Follow:

  • E-mail
  • LinkedIn
  • RSS
  • Twitter
  • YouTube

Copyright © 2025 Mocappys.com