diff --git a/rigify/__init__.py b/rigify/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..0609b709fb51b447e063a17bb797642f59a8cef0
--- /dev/null
+++ b/rigify/__init__.py
@@ -0,0 +1,138 @@
+#====================== BEGIN GPL LICENSE BLOCK ======================
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software Foundation,
+#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+#======================= END GPL LICENSE BLOCK ========================
+
+bl_addon_info = {
+    "name": "Rigify",
+    "author": "Nathan Vegdahl",
+    "version": (0, 5),
+    "blender": (2, 5, 5),
+    "api": 33110,
+    "location": "Armature properties",
+    "wiki_url": "",
+    "tracker_url": "",
+    "category": "Rigging"}
+
+import bpy
+import bpy_types
+import os
+from imp import reload
+
+
+try:
+    reload(generate)
+    reload(ui)
+    reload(utils)
+    reload(metarig_menu)
+except NameError:
+    from rigify import generate, ui, utils, metarig_menu
+
+
+def get_rig_list(path):
+    """ Recursively searches for rig types, and returns a list.
+    """
+    rigs = []
+    files = os.listdir(os.path.dirname(__file__) + "/" + utils.RIG_DIR + "/" + path)
+    files = sorted(files)
+
+    for f in files:
+        if not f.startswith("_"):
+            if os.path.isdir(os.path.dirname(__file__) + "/" + utils.RIG_DIR + "/" + path + f):
+                # Check directories
+                try:
+                    rig = utils.get_rig_type((path + f).replace("/", "."))
+                except ImportError as e:
+                    print("Rigify: " + str(e))
+                else:
+                    # Check if it's a rig itself
+                    try:
+                        rig.Rig
+                    except AttributeError:
+                        # Check for sub-rigs
+                        ls = get_rig_list(path + f + "/")
+                        for l in ls:
+                            rigs += [f + '.' + l]
+                    else:
+                        rigs += [f]
+
+            elif f.endswith(".py"):
+                # Check straight-up python files
+                t = f[:-3]
+                try:
+                    utils.get_rig_type((path + t).replace("/", ".")).Rig
+                except (ImportError, AttributeError):
+                    pass
+                else:
+                    rigs += [t]
+    rigs.sort()
+    return rigs
+
+
+rig_list = get_rig_list("")
+
+
+collection_list = []
+for r in rig_list:
+    a = r.split(".")
+    if len(a) >= 2 and a[0] not in collection_list:
+        collection_list += [a[0]]
+
+
+col_enum_list = [("All", "All", ""), ("None", "None", "")]
+for c in collection_list:
+    col_enum_list += [(c, c, "")]
+
+
+class RigifyName(bpy.types.IDPropertyGroup):
+    name = bpy.props.StringProperty()
+
+
+class RigifyParameters(bpy.types.IDPropertyGroup):
+    name = bpy.props.StringProperty()
+
+
+for rig in rig_list:
+    r = utils.get_rig_type(rig).Rig
+    try:
+        r.add_parameters(RigifyParameters)
+    except AttributeError:
+        pass
+
+
+##### REGISTER #####
+
+def register():
+    bpy.types.PoseBone.rigify_type = bpy.props.StringProperty(name="Rigify Type", description="Rig type for this bone.")
+    bpy.types.PoseBone.rigify_parameters = bpy.props.CollectionProperty(type=RigifyParameters)
+
+    bpy.types.Scene.rigify_collection = bpy.props.EnumProperty(items=col_enum_list, default="All", name="Rigify Active Collection", description="The selected rig collection")
+    bpy.types.Scene.rigify_types = bpy.props.CollectionProperty(type=RigifyName)
+    bpy.types.Scene.rigify_active_type = bpy.props.IntProperty(name="Rigify Active Type", description="The selected rig type.")
+
+    metarig_menu.register()
+
+
+def unregister():
+    del bpy.types.PoseBone.rigify_type
+    del bpy.types.PoseBone.rigify_parameters
+
+    del bpy.types.Scene.rigify_collection
+    del bpy.types.Scene.rigify_types
+    del bpy.types.Scene.rigify_active_type
+
+    metarig_menu.unregister()
+
diff --git a/rigify/generate.py b/rigify/generate.py
new file mode 100644
index 0000000000000000000000000000000000000000..1134b6d6025cdbfa35b30fe679449418b197c591
--- /dev/null
+++ b/rigify/generate.py
@@ -0,0 +1,351 @@
+#====================== BEGIN GPL LICENSE BLOCK ======================
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software Foundation,
+#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+#======================= END GPL LICENSE BLOCK ========================
+
+import bpy
+import time
+import traceback
+import sys
+from rna_prop_ui import rna_idprop_ui_prop_get
+from rigify.utils import MetarigError, new_bone, get_rig_type
+from rigify.utils import ORG_PREFIX, MCH_PREFIX, DEF_PREFIX, WGT_PREFIX, ROOT_NAME, make_original_name
+from rigify.utils import RIG_DIR
+from rigify.utils import create_root_widget
+from rigify.utils import random_string
+from rigify.rig_ui_template import UI_SLIDERS, layers_ui
+from rigify import rigs
+
+RIG_MODULE = "rigs"
+ORG_LAYER = [n == 31 for n in range(0, 32)]  # Armature layer that original bones should be moved to.
+MCH_LAYER = [n == 30 for n in range(0, 32)]  # Armature layer that mechanism bones should be moved to.
+DEF_LAYER = [n == 29 for n in range(0, 32)]  # Armature layer that deformation bones should be moved to.
+ROOT_LAYER = [n == 28 for n in range(0, 32)]  # Armature layer that root bone should be moved to.
+
+
+class Timer:
+    def __init__(self):
+        self.timez = time.time()
+
+    def tick(self, string):
+        t = time.time()
+        print(string + "%.3f" % (t - self.timez))
+        self.timez = t
+
+
+# TODO: generalize to take a group as input instead of an armature.
+def generate_rig(context, metarig):
+    """ Generates a rig from a metarig.
+
+    """
+    t = Timer()
+    rig_id = random_string(12)  # Random so that different rigs don't collide id's
+
+    # Initial configuration
+    use_global_undo = context.user_preferences.edit.use_global_undo
+    context.user_preferences.edit.use_global_undo = False
+    mode_orig = context.mode
+    rest_backup = metarig.data.pose_position
+    metarig.data.pose_position = 'REST'
+
+    bpy.ops.object.mode_set(mode='OBJECT')
+
+    scene = context.scene
+
+    #------------------------------------------
+    # Create/find the rig object and set it up
+
+    # Check if the generated rig already exists, so we can
+    # regenerate in the same object.  If not, create a new
+    # object to generate the rig in.
+    print("Fetch rig.")
+    try:
+        name = metarig["rig_object_name"]
+    except KeyError:
+        name = "rig"
+
+    try:
+        obj = scene.objects[name]
+    except KeyError:
+        obj = bpy.data.objects.new(name, bpy.data.armatures.new(name))
+        obj.draw_type = 'WIRE'
+        scene.objects.link(obj)
+
+    obj.data.pose_position = 'POSE'
+
+    # Get rid of anim data in case the rig already existed
+    print("Clear rig animation data.")
+    obj.animation_data_clear()
+
+    # Select generated rig object
+    metarig.select = False
+    obj.select = True
+    scene.objects.active = obj
+
+    # Remove all bones from the generated rig armature.
+    bpy.ops.object.mode_set(mode='EDIT')
+    for bone in obj.data.edit_bones:
+        obj.data.edit_bones.remove(bone)
+    bpy.ops.object.mode_set(mode='OBJECT')
+
+    # Create temporary duplicates for merging
+    temp_rig_1 = metarig.copy()
+    temp_rig_1.data = metarig.data.copy()
+    scene.objects.link(temp_rig_1)
+
+    temp_rig_2 = metarig.copy()
+    temp_rig_2.data = obj.data
+    scene.objects.link(temp_rig_2)
+
+    # Select the temp rigs for merging
+    for objt in scene.objects:
+        objt.select = False  # deselect all objects
+    temp_rig_1.select = True
+    temp_rig_2.select = True
+    scene.objects.active = temp_rig_2
+
+    # Merge the temporary rigs
+    bpy.ops.object.join()
+
+    # Delete the second temp rig
+    bpy.ops.object.delete()
+
+    # Select the generated rig
+    for objt in scene.objects:
+        objt.select = False  # deselect all objects
+    obj.select = True
+    scene.objects.active = obj
+
+    # Copy over the pose_bone properties
+    for bone in metarig.pose.bones:
+        bone_gen = obj.pose.bones[bone.name]
+
+        # Rotation mode and transform locks
+        bone_gen.rotation_mode = bone.rotation_mode
+        bone_gen.lock_rotation = tuple(bone.lock_rotation)
+        bone_gen.lock_rotation_w = bone.lock_rotation_w
+        bone_gen.lock_rotations_4d = bone.lock_rotations_4d
+        bone_gen.lock_location = tuple(bone.lock_location)
+        bone_gen.lock_scale = tuple(bone.lock_scale)
+
+        # Custom properties
+        for prop in bone.keys():
+            bone_gen[prop] = bone[prop]
+
+    # Copy over bone properties
+    for bone in metarig.data.bones:
+        bone_gen = obj.data.bones[bone.name]
+
+        # B-bone stuff
+        bone_gen.bbone_segments = bone.bbone_segments
+        bone_gen.bbone_in = bone.bbone_in
+        bone_gen.bbone_out = bone.bbone_out
+
+    t.tick("Duplicate rig: ")
+    #----------------------------------
+    # Make a list of the original bones so we can keep track of them.
+    original_bones = [bone.name for bone in obj.data.bones]
+
+    # Add the ORG_PREFIX to the original bones.
+    bpy.ops.object.mode_set(mode='OBJECT')
+    for i in range(0, len(original_bones)):
+        obj.data.bones[original_bones[i]].name = make_original_name(original_bones[i])
+        original_bones[i] = make_original_name(original_bones[i])
+
+    # Create a sorted list of the original bones, sorted in the order we're
+    # going to traverse them for rigging.
+    # (root-most -> leaf-most, alphabetical)
+    bones_sorted = []
+    for name in original_bones:
+        bones_sorted += [name]
+    bones_sorted.sort()  # first sort by names
+    bones_sorted.sort(key=lambda bone: len(obj.pose.bones[bone].parent_recursive))  # then parents before children
+
+    t.tick("Make list of org bones: ")
+    #----------------------------------
+    # Create the root bone.
+    bpy.ops.object.mode_set(mode='EDIT')
+    root_bone = new_bone(obj, ROOT_NAME)
+    obj.data.edit_bones[root_bone].head = (0, 0, 0)
+    obj.data.edit_bones[root_bone].tail = (0, 1, 0)
+    obj.data.edit_bones[root_bone].roll = 0
+    bpy.ops.object.mode_set(mode='OBJECT')
+    obj.data.bones[root_bone].layers = ROOT_LAYER
+    # Put the rig_name in the armature custom properties
+    rna_idprop_ui_prop_get(obj.data, "rig_id", create=True)
+    obj.data["rig_id"] = rig_id
+
+    t.tick("Create root bone: ")
+    #----------------------------------
+    try:
+        # Collect/initialize all the rigs.
+        rigs = []
+        deformation_rigs = []
+        for bone in bones_sorted:
+            bpy.ops.object.mode_set(mode='EDIT')
+            rigs += get_bone_rigs(obj, bone)
+        t.tick("Initialize rigs: ")
+
+        # Generate all the rigs.
+        ui_scripts = []
+        for rig in rigs:
+            # Go into editmode in the rig armature
+            bpy.ops.object.mode_set(mode='OBJECT')
+            context.scene.objects.active = obj
+            obj.select = True
+            bpy.ops.object.mode_set(mode='EDIT')
+            scripts = rig.generate()
+            if scripts != None:
+                ui_scripts += [scripts[0]]
+        t.tick("Generate rigs: ")
+    except Exception as e:
+        # Cleanup if something goes wrong
+        print("Rigify: failed to generate rig.")
+        context.user_preferences.edit.use_global_undo = use_global_undo
+        metarig.data.pose_position = rest_backup
+        obj.data.pose_position = 'POSE'
+        bpy.ops.object.mode_set(mode='OBJECT')
+
+        # Continue the exception
+        raise e
+
+    #----------------------------------
+    bpy.ops.object.mode_set(mode='OBJECT')
+
+    # Get a list of all the bones in the armature
+    bones = [bone.name for bone in obj.data.bones]
+
+    # Parent any free-floating bones to the root.
+    bpy.ops.object.mode_set(mode='EDIT')
+    for bone in bones:
+        if obj.data.edit_bones[bone].parent == None:
+            obj.data.edit_bones[bone].use_connect = False
+            obj.data.edit_bones[bone].parent = obj.data.edit_bones[root_bone]
+    bpy.ops.object.mode_set(mode='OBJECT')
+
+    # Every bone that has a name starting with "DEF-" make deforming.  All the
+    # others make non-deforming.
+    for bone in bones:
+        if obj.data.bones[bone].name.startswith(DEF_PREFIX):
+            obj.data.bones[bone].use_deform = True
+        else:
+            obj.data.bones[bone].use_deform = False
+
+    # Move all the original bones to their layer.
+    for bone in original_bones:
+        obj.data.bones[bone].layers = ORG_LAYER
+
+    # Move all the bones with names starting with "MCH-" to their layer.
+    for bone in bones:
+        if obj.data.bones[bone].name.startswith(MCH_PREFIX):
+            obj.data.bones[bone].layers = MCH_LAYER
+
+    # Move all the bones with names starting with "DEF-" to their layer.
+    for bone in bones:
+        if obj.data.bones[bone].name.startswith(DEF_PREFIX):
+            obj.data.bones[bone].layers = DEF_LAYER
+
+    # Create root bone widget
+    create_root_widget(obj, "root")
+
+    # Assign shapes to bones
+    # Object's with name WGT-<bone_name> get used as that bone's shape.
+    for bone in bones:
+        wgt_name = (WGT_PREFIX + obj.data.bones[bone].name)[:21]  # Object names are limited to 21 characters... arg
+        if wgt_name in context.scene.objects:
+            # Weird temp thing because it won't let me index by object name
+            for ob in context.scene.objects:
+                if ob.name == wgt_name:
+                    obj.pose.bones[bone].custom_shape = ob
+                    break
+            # This is what it should do:
+            # obj.pose.bones[bone].custom_shape = context.scene.objects[wgt_name]
+    # Reveal all the layers with control bones on them
+    vis_layers = [False for n in range(0, 32)]
+    for bone in bones:
+        for i in range(0, 32):
+            vis_layers[i] = vis_layers[i] or obj.data.bones[bone].layers[i]
+    for i in range(0, 32):
+        vis_layers[i] = vis_layers[i] and not (ORG_LAYER[i] or MCH_LAYER[i] or DEF_LAYER[i])
+    obj.data.layers = vis_layers
+
+    # Generate the UI script
+    if "rig_ui.py" in bpy.data.texts:
+        script = bpy.data.texts["rig_ui.py"]
+        script.clear()
+    else:
+        script = bpy.data.texts.new("rig_ui.py")
+    script.write(UI_SLIDERS % rig_id)
+    for s in ui_scripts:
+        script.write("\n        " + s.replace("\n", "\n        ") + "\n")
+    script.write(layers_ui(vis_layers))
+    script.use_module = True
+
+    t.tick("The rest: ")
+    #----------------------------------
+    # Deconfigure
+    bpy.ops.object.mode_set(mode='OBJECT')
+    metarig.data.pose_position = rest_backup
+    obj.data.pose_position = 'POSE'
+    context.user_preferences.edit.use_global_undo = use_global_undo
+
+
+def get_bone_rigs(obj, bone_name, halt_on_missing=False):
+    """ Fetch all the rigs specified on a bone.
+    """
+    rigs = []
+    rig_type = obj.pose.bones[bone_name].rigify_type
+    rig_type = rig_type.replace(" ", "")
+
+    if rig_type == "":
+        pass
+    else:
+        # Gather parameters
+        try:
+            params = obj.pose.bones[bone_name].rigify_parameters[0]
+        except (KeyError, IndexError):
+            params = None
+
+        # Get the rig
+        try:
+            rig = get_rig_type(rig_type).Rig(obj, bone_name, params)
+        except ImportError:
+            message = "Rig Type Missing: python module for type '%s' not found (bone: %s)" % (t, bone_name)
+            if halt_on_missing:
+                raise MetarigError(message)
+            else:
+                print(message)
+                print('print_exc():')
+                traceback.print_exc(file=sys.stdout)
+        else:
+            rigs += [rig]
+    return rigs
+
+
+def param_matches_type(param_name, rig_type):
+    """ Returns True if the parameter name is consistent with the rig type.
+    """
+    if param_name.rsplit(".", 1)[0] == rig_type:
+        return True
+    else:
+        return False
+
+
+def param_name(param_name, rig_type):
+    """ Get the actual parameter name, sans-rig-type.
+    """
+    return param_name[len(rig_type) + 1:]
+
diff --git a/rigify/metarig_menu.py b/rigify/metarig_menu.py
new file mode 100644
index 0000000000000000000000000000000000000000..65dbbce96a244c687b6768507ceafe4d50a59aff
--- /dev/null
+++ b/rigify/metarig_menu.py
@@ -0,0 +1,56 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software Foundation,
+#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+import bpy
+import mathutils
+from rigify.metarigs import human
+from math import cos, sin, pi
+
+
+class AddHuman(bpy.types.Operator):
+    '''Add an advanced human metarig base'''
+    bl_idname = "object.armature_human_advanced_add"
+    bl_label = "Add Humanoid (advanced metarig)"
+    bl_options = {'REGISTER', 'UNDO'}
+
+    def execute(self, context):
+        bpy.ops.object.armature_add()
+        obj = context.active_object
+        mode_orig = obj.mode
+        bpy.ops.object.mode_set(mode='EDIT')  # grr, remove bone
+        bones = context.active_object.data.edit_bones
+        bones.remove(bones[0])
+        human.create(obj)
+        bpy.ops.object.mode_set(mode=mode_orig)
+        return {'FINISHED'}
+
+
+# Add to a menu
+menu_func = (lambda self, context: self.layout.operator(AddHuman.bl_idname,
+                    icon='OUTLINER_OB_ARMATURE', text="Human (Meta-Rig)"))
+
+
+def register():
+    #bpy.types.register(AddHuman)
+    bpy.types.INFO_MT_armature_add.append(menu_func)
+
+
+def unregister():
+    #bpy.types.unregister(AddHuman)
+    bpy.types.INFO_MT_armature_add.remove(menu_func)
+
diff --git a/rigify/metarigs/__init__.py b/rigify/metarigs/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/rigify/metarigs/human.py b/rigify/metarigs/human.py
new file mode 100644
index 0000000000000000000000000000000000000000..08f8b230e93f1deea7225390ce3da426cb8de1d4
--- /dev/null
+++ b/rigify/metarigs/human.py
@@ -0,0 +1,1087 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software Foundation,
+#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+import bpy
+
+
+def create(obj):
+    # generated by rigify.utils.write_metarig
+    bpy.ops.object.mode_set(mode='EDIT')
+    arm = obj.data
+
+    bones = {}
+
+    bone = arm.edit_bones.new('hips')
+    bone.head[:] = 0.0000, 0.0552, 1.0099
+    bone.tail[:] = 0.0000, 0.0172, 1.1837
+    bone.roll = -3.1416
+    bone.use_connect = False
+    bones['hips'] = bone.name
+    bone = arm.edit_bones.new('spine')
+    bone.head[:] = 0.0000, 0.0172, 1.1837
+    bone.tail[:] = 0.0000, 0.0004, 1.3418
+    bone.roll = -3.1416
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['hips']]
+    bones['spine'] = bone.name
+    bone = arm.edit_bones.new('thigh.L')
+    bone.head[:] = 0.0980, 0.0124, 1.0720
+    bone.tail[:] = 0.0980, -0.0286, 0.5372
+    bone.roll = 0.0000
+    bone.use_connect = False
+    bone.parent = arm.edit_bones[bones['hips']]
+    bones['thigh.L'] = bone.name
+    bone = arm.edit_bones.new('thigh.R')
+    bone.head[:] = -0.0980, 0.0124, 1.0720
+    bone.tail[:] = -0.0980, -0.0286, 0.5372
+    bone.roll = 0.0000
+    bone.use_connect = False
+    bone.parent = arm.edit_bones[bones['hips']]
+    bones['thigh.R'] = bone.name
+    bone = arm.edit_bones.new('ribs')
+    bone.head[:] = 0.0000, 0.0004, 1.3418
+    bone.tail[:] = 0.0000, 0.0114, 1.6582
+    bone.roll = -3.1416
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['spine']]
+    bones['ribs'] = bone.name
+    bone = arm.edit_bones.new('shin.L')
+    bone.head[:] = 0.0980, -0.0286, 0.5372
+    bone.tail[:] = 0.0980, 0.0162, 0.0852
+    bone.roll = 0.0000
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['thigh.L']]
+    bones['shin.L'] = bone.name
+    bone = arm.edit_bones.new('shin.R')
+    bone.head[:] = -0.0980, -0.0286, 0.5372
+    bone.tail[:] = -0.0980, 0.0162, 0.0852
+    bone.roll = 0.0000
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['thigh.R']]
+    bones['shin.R'] = bone.name
+    bone = arm.edit_bones.new('neck')
+    bone.head[:] = 0.0000, 0.0114, 1.6582
+    bone.tail[:] = 0.0000, -0.0247, 1.7813
+    bone.roll = 3.1416
+    bone.use_connect = False
+    bone.parent = arm.edit_bones[bones['ribs']]
+    bones['neck'] = bone.name
+    bone = arm.edit_bones.new('shoulder.L')
+    bone.head[:] = 0.0183, -0.0684, 1.6051
+    bone.tail[:] = 0.1694, 0.0205, 1.6050
+    bone.roll = 0.0004
+    bone.use_connect = False
+    bone.parent = arm.edit_bones[bones['ribs']]
+    bones['shoulder.L'] = bone.name
+    bone = arm.edit_bones.new('shoulder.R')
+    bone.head[:] = -0.0183, -0.0684, 1.6051
+    bone.tail[:] = -0.1694, 0.0205, 1.6050
+    bone.roll = -0.0004
+    bone.use_connect = False
+    bone.parent = arm.edit_bones[bones['ribs']]
+    bones['shoulder.R'] = bone.name
+    bone = arm.edit_bones.new('foot.L')
+    bone.head[:] = 0.0980, 0.0162, 0.0852
+    bone.tail[:] = 0.0980, -0.0934, 0.0167
+    bone.roll = 0.0000
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['shin.L']]
+    bones['foot.L'] = bone.name
+    bone = arm.edit_bones.new('heel.L')
+    bone.head[:] = 0.0980, 0.0162, 0.0852
+    bone.tail[:] = 0.0980, 0.0882, -0.0000
+    bone.roll = -3.1416
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['shin.L']]
+    bones['heel.L'] = bone.name
+    bone = arm.edit_bones.new('foot.R')
+    bone.head[:] = -0.0980, 0.0162, 0.0852
+    bone.tail[:] = -0.0980, -0.0934, 0.0167
+    bone.roll = -0.0000
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['shin.R']]
+    bones['foot.R'] = bone.name
+    bone = arm.edit_bones.new('heel.R')
+    bone.head[:] = -0.0980, 0.0162, 0.0852
+    bone.tail[:] = -0.0980, 0.0882, -0.0000
+    bone.roll = 3.1416
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['shin.R']]
+    bones['heel.R'] = bone.name
+    bone = arm.edit_bones.new('head')
+    bone.head[:] = 0.0000, -0.0247, 1.7813
+    bone.tail[:] = 0.0000, -0.0247, 1.9347
+    bone.roll = 3.1416
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['neck']]
+    bones['head'] = bone.name
+    bone = arm.edit_bones.new('upper_arm.L')
+    bone.head[:] = 0.1953, 0.0267, 1.5846
+    bone.tail[:] = 0.4424, 0.0885, 1.4491
+    bone.roll = 2.0691
+    bone.use_connect = False
+    bone.parent = arm.edit_bones[bones['shoulder.L']]
+    bones['upper_arm.L'] = bone.name
+    bone = arm.edit_bones.new('upper_arm.R')
+    bone.head[:] = -0.1953, 0.0267, 1.5846
+    bone.tail[:] = -0.4424, 0.0885, 1.4491
+    bone.roll = -2.0691
+    bone.use_connect = False
+    bone.parent = arm.edit_bones[bones['shoulder.R']]
+    bones['upper_arm.R'] = bone.name
+    bone = arm.edit_bones.new('toe.L')
+    bone.head[:] = 0.0980, -0.0934, 0.0167
+    bone.tail[:] = 0.0980, -0.1606, 0.0167
+    bone.roll = -0.0000
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['foot.L']]
+    bones['toe.L'] = bone.name
+    bone = arm.edit_bones.new('toe.R')
+    bone.head[:] = -0.0980, -0.0934, 0.0167
+    bone.tail[:] = -0.0980, -0.1606, 0.0167
+    bone.roll = 0.0000
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['foot.R']]
+    bones['toe.R'] = bone.name
+    bone = arm.edit_bones.new('forearm.L')
+    bone.head[:] = 0.4424, 0.0885, 1.4491
+    bone.tail[:] = 0.6594, 0.0492, 1.3061
+    bone.roll = 2.1459
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['upper_arm.L']]
+    bones['forearm.L'] = bone.name
+    bone = arm.edit_bones.new('forearm.R')
+    bone.head[:] = -0.4424, 0.0885, 1.4491
+    bone.tail[:] = -0.6594, 0.0492, 1.3061
+    bone.roll = -2.1459
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['upper_arm.R']]
+    bones['forearm.R'] = bone.name
+    bone = arm.edit_bones.new('hand.L')
+    bone.head[:] = 0.6594, 0.0492, 1.3061
+    bone.tail[:] = 0.7234, 0.0412, 1.2585
+    bone.roll = -2.4946
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['forearm.L']]
+    bones['hand.L'] = bone.name
+    bone = arm.edit_bones.new('hand.R')
+    bone.head[:] = -0.6594, 0.0492, 1.3061
+    bone.tail[:] = -0.7234, 0.0412, 1.2585
+    bone.roll = 2.4946
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['forearm.R']]
+    bones['hand.R'] = bone.name
+    bone = arm.edit_bones.new('palm.01.L')
+    bone.head[:] = 0.6921, 0.0224, 1.2882
+    bone.tail[:] = 0.7464, 0.0051, 1.2482
+    bone.roll = -2.4928
+    bone.use_connect = False
+    bone.parent = arm.edit_bones[bones['hand.L']]
+    bones['palm.01.L'] = bone.name
+    bone = arm.edit_bones.new('palm.02.L')
+    bone.head[:] = 0.6970, 0.0389, 1.2877
+    bone.tail[:] = 0.7518, 0.0277, 1.2487
+    bone.roll = -2.5274
+    bone.use_connect = False
+    bone.parent = arm.edit_bones[bones['hand.L']]
+    bones['palm.02.L'] = bone.name
+    bone = arm.edit_bones.new('palm.03.L')
+    bone.head[:] = 0.6963, 0.0545, 1.2874
+    bone.tail[:] = 0.7540, 0.0521, 1.2482
+    bone.roll = -2.5843
+    bone.use_connect = False
+    bone.parent = arm.edit_bones[bones['hand.L']]
+    bones['palm.03.L'] = bone.name
+    bone = arm.edit_bones.new('palm.04.L')
+    bone.head[:] = 0.6929, 0.0696, 1.2871
+    bone.tail[:] = 0.7528, 0.0763, 1.2428
+    bone.roll = -2.5155
+    bone.use_connect = False
+    bone.parent = arm.edit_bones[bones['hand.L']]
+    bones['palm.04.L'] = bone.name
+    bone = arm.edit_bones.new('palm.01.R')
+    bone.head[:] = -0.6921, 0.0224, 1.2882
+    bone.tail[:] = -0.7464, 0.0051, 1.2482
+    bone.roll = 2.4928
+    bone.use_connect = False
+    bone.parent = arm.edit_bones[bones['hand.R']]
+    bones['palm.01.R'] = bone.name
+    bone = arm.edit_bones.new('palm.02.R')
+    bone.head[:] = -0.6970, 0.0389, 1.2877
+    bone.tail[:] = -0.7518, 0.0277, 1.2487
+    bone.roll = 2.5274
+    bone.use_connect = False
+    bone.parent = arm.edit_bones[bones['hand.R']]
+    bones['palm.02.R'] = bone.name
+    bone = arm.edit_bones.new('palm.03.R')
+    bone.head[:] = -0.6963, 0.0544, 1.2874
+    bone.tail[:] = -0.7540, 0.0521, 1.2482
+    bone.roll = 2.5843
+    bone.use_connect = False
+    bone.parent = arm.edit_bones[bones['hand.R']]
+    bones['palm.03.R'] = bone.name
+    bone = arm.edit_bones.new('palm.04.R')
+    bone.head[:] = -0.6929, 0.0696, 1.2871
+    bone.tail[:] = -0.7528, 0.0763, 1.2428
+    bone.roll = 2.5155
+    bone.use_connect = False
+    bone.parent = arm.edit_bones[bones['hand.R']]
+    bones['palm.04.R'] = bone.name
+    bone = arm.edit_bones.new('finger_index.01.L')
+    bone.head[:] = 0.7464, 0.0051, 1.2482
+    bone.tail[:] = 0.7718, 0.0013, 1.2112
+    bone.roll = -2.0315
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['palm.01.L']]
+    bones['finger_index.01.L'] = bone.name
+    bone = arm.edit_bones.new('thumb.01.L')
+    bone.head[:] = 0.6705, 0.0214, 1.2738
+    bone.tail[:] = 0.6857, 0.0015, 1.2404
+    bone.roll = -0.1587
+    bone.use_connect = False
+    bone.parent = arm.edit_bones[bones['palm.01.L']]
+    bones['thumb.01.L'] = bone.name
+    bone = arm.edit_bones.new('finger_middle.01.L')
+    bone.head[:] = 0.7518, 0.0277, 1.2487
+    bone.tail[:] = 0.7762, 0.0234, 1.2058
+    bone.roll = -2.0067
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['palm.02.L']]
+    bones['finger_middle.01.L'] = bone.name
+    bone = arm.edit_bones.new('finger_ring.01.L')
+    bone.head[:] = 0.7540, 0.0521, 1.2482
+    bone.tail[:] = 0.7715, 0.0499, 1.2070
+    bone.roll = -2.0082
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['palm.03.L']]
+    bones['finger_ring.01.L'] = bone.name
+    bone = arm.edit_bones.new('finger_pinky.01.L')
+    bone.head[:] = 0.7528, 0.0763, 1.2428
+    bone.tail[:] = 0.7589, 0.0765, 1.2156
+    bone.roll = -1.9749
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['palm.04.L']]
+    bones['finger_pinky.01.L'] = bone.name
+    bone = arm.edit_bones.new('finger_index.01.R')
+    bone.head[:] = -0.7464, 0.0051, 1.2482
+    bone.tail[:] = -0.7718, 0.0012, 1.2112
+    bone.roll = 2.0315
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['palm.01.R']]
+    bones['finger_index.01.R'] = bone.name
+    bone = arm.edit_bones.new('thumb.01.R')
+    bone.head[:] = -0.6705, 0.0214, 1.2738
+    bone.tail[:] = -0.6857, 0.0015, 1.2404
+    bone.roll = 0.1587
+    bone.use_connect = False
+    bone.parent = arm.edit_bones[bones['palm.01.R']]
+    bones['thumb.01.R'] = bone.name
+    bone = arm.edit_bones.new('finger_middle.01.R')
+    bone.head[:] = -0.7518, 0.0277, 1.2487
+    bone.tail[:] = -0.7762, 0.0233, 1.2058
+    bone.roll = 2.0067
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['palm.02.R']]
+    bones['finger_middle.01.R'] = bone.name
+    bone = arm.edit_bones.new('finger_ring.01.R')
+    bone.head[:] = -0.7540, 0.0521, 1.2482
+    bone.tail[:] = -0.7715, 0.0499, 1.2070
+    bone.roll = 2.0082
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['palm.03.R']]
+    bones['finger_ring.01.R'] = bone.name
+    bone = arm.edit_bones.new('finger_pinky.01.R')
+    bone.head[:] = -0.7528, 0.0763, 1.2428
+    bone.tail[:] = -0.7589, 0.0765, 1.2156
+    bone.roll = 1.9749
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['palm.04.R']]
+    bones['finger_pinky.01.R'] = bone.name
+    bone = arm.edit_bones.new('finger_index.02.L')
+    bone.head[:] = 0.7718, 0.0013, 1.2112
+    bone.tail[:] = 0.7840, -0.0003, 1.1858
+    bone.roll = -1.8799
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['finger_index.01.L']]
+    bones['finger_index.02.L'] = bone.name
+    bone = arm.edit_bones.new('thumb.02.L')
+    bone.head[:] = 0.6857, 0.0015, 1.2404
+    bone.tail[:] = 0.7056, -0.0057, 1.2145
+    bone.roll = -0.4798
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['thumb.01.L']]
+    bones['thumb.02.L'] = bone.name
+    bone = arm.edit_bones.new('finger_middle.02.L')
+    bone.head[:] = 0.7762, 0.0234, 1.2058
+    bone.tail[:] = 0.7851, 0.0218, 1.1749
+    bone.roll = -1.8283
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['finger_middle.01.L']]
+    bones['finger_middle.02.L'] = bone.name
+    bone = arm.edit_bones.new('finger_ring.02.L')
+    bone.head[:] = 0.7715, 0.0499, 1.2070
+    bone.tail[:] = 0.7794, 0.0494, 1.1762
+    bone.roll = -1.8946
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['finger_ring.01.L']]
+    bones['finger_ring.02.L'] = bone.name
+    bone = arm.edit_bones.new('finger_pinky.02.L')
+    bone.head[:] = 0.7589, 0.0765, 1.2156
+    bone.tail[:] = 0.7618, 0.0770, 1.1932
+    bone.roll = -1.9059
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['finger_pinky.01.L']]
+    bones['finger_pinky.02.L'] = bone.name
+    bone = arm.edit_bones.new('finger_index.02.R')
+    bone.head[:] = -0.7718, 0.0012, 1.2112
+    bone.tail[:] = -0.7840, -0.0003, 1.1858
+    bone.roll = 1.8799
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['finger_index.01.R']]
+    bones['finger_index.02.R'] = bone.name
+    bone = arm.edit_bones.new('thumb.02.R')
+    bone.head[:] = -0.6857, 0.0015, 1.2404
+    bone.tail[:] = -0.7056, -0.0057, 1.2145
+    bone.roll = 0.4798
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['thumb.01.R']]
+    bones['thumb.02.R'] = bone.name
+    bone = arm.edit_bones.new('finger_middle.02.R')
+    bone.head[:] = -0.7762, 0.0233, 1.2058
+    bone.tail[:] = -0.7851, 0.0218, 1.1749
+    bone.roll = 1.8283
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['finger_middle.01.R']]
+    bones['finger_middle.02.R'] = bone.name
+    bone = arm.edit_bones.new('finger_ring.02.R')
+    bone.head[:] = -0.7715, 0.0499, 1.2070
+    bone.tail[:] = -0.7794, 0.0494, 1.1762
+    bone.roll = 1.8946
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['finger_ring.01.R']]
+    bones['finger_ring.02.R'] = bone.name
+    bone = arm.edit_bones.new('finger_pinky.02.R')
+    bone.head[:] = -0.7589, 0.0765, 1.2156
+    bone.tail[:] = -0.7618, 0.0770, 1.1932
+    bone.roll = 1.9059
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['finger_pinky.01.R']]
+    bones['finger_pinky.02.R'] = bone.name
+    bone = arm.edit_bones.new('finger_index.03.L')
+    bone.head[:] = 0.7840, -0.0003, 1.1858
+    bone.tail[:] = 0.7892, 0.0006, 1.1636
+    bone.roll = -1.6760
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['finger_index.02.L']]
+    bones['finger_index.03.L'] = bone.name
+    bone = arm.edit_bones.new('thumb.03.L')
+    bone.head[:] = 0.7056, -0.0057, 1.2145
+    bone.tail[:] = 0.7194, -0.0098, 1.1995
+    bone.roll = -0.5826
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['thumb.02.L']]
+    bones['thumb.03.L'] = bone.name
+    bone = arm.edit_bones.new('finger_middle.03.L')
+    bone.head[:] = 0.7851, 0.0218, 1.1749
+    bone.tail[:] = 0.7888, 0.0216, 1.1525
+    bone.roll = -1.7483
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['finger_middle.02.L']]
+    bones['finger_middle.03.L'] = bone.name
+    bone = arm.edit_bones.new('finger_ring.03.L')
+    bone.head[:] = 0.7794, 0.0494, 1.1762
+    bone.tail[:] = 0.7781, 0.0498, 1.1577
+    bone.roll = -1.6582
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['finger_ring.02.L']]
+    bones['finger_ring.03.L'] = bone.name
+    bone = arm.edit_bones.new('finger_pinky.03.L')
+    bone.head[:] = 0.7618, 0.0770, 1.1932
+    bone.tail[:] = 0.7611, 0.0772, 1.1782
+    bone.roll = -1.7639
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['finger_pinky.02.L']]
+    bones['finger_pinky.03.L'] = bone.name
+    bone = arm.edit_bones.new('finger_index.03.R')
+    bone.head[:] = -0.7840, -0.0003, 1.1858
+    bone.tail[:] = -0.7892, 0.0006, 1.1636
+    bone.roll = 1.6760
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['finger_index.02.R']]
+    bones['finger_index.03.R'] = bone.name
+    bone = arm.edit_bones.new('thumb.03.R')
+    bone.head[:] = -0.7056, -0.0057, 1.2145
+    bone.tail[:] = -0.7194, -0.0098, 1.1995
+    bone.roll = 0.5826
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['thumb.02.R']]
+    bones['thumb.03.R'] = bone.name
+    bone = arm.edit_bones.new('finger_middle.03.R')
+    bone.head[:] = -0.7851, 0.0218, 1.1749
+    bone.tail[:] = -0.7888, 0.0216, 1.1525
+    bone.roll = 1.7483
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['finger_middle.02.R']]
+    bones['finger_middle.03.R'] = bone.name
+    bone = arm.edit_bones.new('finger_ring.03.R')
+    bone.head[:] = -0.7794, 0.0494, 1.1762
+    bone.tail[:] = -0.7781, 0.0498, 1.1577
+    bone.roll = 1.6582
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['finger_ring.02.R']]
+    bones['finger_ring.03.R'] = bone.name
+    bone = arm.edit_bones.new('finger_pinky.03.R')
+    bone.head[:] = -0.7618, 0.0770, 1.1932
+    bone.tail[:] = -0.7611, 0.0772, 1.1782
+    bone.roll = 1.7639
+    bone.use_connect = True
+    bone.parent = arm.edit_bones[bones['finger_pinky.02.R']]
+    bones['finger_pinky.03.R'] = bone.name
+
+    bpy.ops.object.mode_set(mode='OBJECT')
+    pbone = obj.pose.bones[bones['hips']]
+    pbone.rigify_type = 'spine'
+    pbone.lock_location = (False, False, False)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['spine']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (False, False, False)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['thigh.L']]
+    pbone.rigify_type = 'biped.leg'
+    pbone.lock_location = (True, True, True)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone.rigify_parameters.add()
+    try:
+        pbone.rigify_parameters[0].separate_ik_layers = True
+    except AttributeError:
+        pass
+    try:
+        pbone.rigify_parameters[0].ik_layers = [False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    except AttributeError:
+        pass
+    pbone = obj.pose.bones[bones['thigh.R']]
+    pbone.rigify_type = 'biped.leg'
+    pbone.lock_location = (True, True, True)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone.rigify_parameters.add()
+    try:
+        pbone.rigify_parameters[0].separate_ik_layers = True
+    except AttributeError:
+        pass
+    try:
+        pbone.rigify_parameters[0].ik_layers = [False, False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    except AttributeError:
+        pass
+    pbone = obj.pose.bones[bones['ribs']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (False, False, False)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['shin.L']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (False, False, False)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['shin.R']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (False, False, False)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['neck']]
+    pbone.rigify_type = 'neck_short'
+    pbone.lock_location = (True, True, True)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['shoulder.L']]
+    pbone.rigify_type = 'copy'
+    pbone.lock_location = (True, True, True)
+    pbone.lock_rotation = (False, True, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'YXZ'
+    pbone.bone.layers = [True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['shoulder.R']]
+    pbone.rigify_type = 'copy'
+    pbone.lock_location = (True, True, True)
+    pbone.lock_rotation = (False, True, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'YXZ'
+    pbone.bone.layers = [True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['foot.L']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (False, False, False)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['heel.L']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (False, False, False)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['foot.R']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (False, False, False)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['heel.R']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (False, False, False)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['head']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (False, False, False)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['upper_arm.L']]
+    pbone.rigify_type = 'biped.arm'
+    pbone.lock_location = (True, True, True)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone.rigify_parameters.add()
+    try:
+        pbone.rigify_parameters[0].separate_ik_layers = True
+    except AttributeError:
+        pass
+    try:
+        pbone.rigify_parameters[0].ik_layers = [False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    except AttributeError:
+        pass
+    pbone = obj.pose.bones[bones['upper_arm.R']]
+    pbone.rigify_type = 'biped.arm'
+    pbone.lock_location = (True, True, True)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone.rigify_parameters.add()
+    try:
+        pbone.rigify_parameters[0].separate_ik_layers = True
+    except AttributeError:
+        pass
+    try:
+        pbone.rigify_parameters[0].ik_layers = [False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    except AttributeError:
+        pass
+    pbone = obj.pose.bones[bones['toe.L']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (False, False, False)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['toe.R']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (False, False, False)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['forearm.L']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (False, False, False)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['forearm.R']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (False, False, False)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['hand.L']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (False, False, False)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['hand.R']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (False, False, False)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['palm.01.L']]
+    pbone.rigify_type = 'palm'
+    pbone.lock_location = (True, True, True)
+    pbone.lock_rotation = (False, True, True)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'YXZ'
+    pbone.bone.layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone.rigify_parameters.add()
+    pbone = obj.pose.bones[bones['palm.02.L']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (True, True, True)
+    pbone.lock_rotation = (False, True, True)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'YXZ'
+    pbone.bone.layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['palm.03.L']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (True, True, True)
+    pbone.lock_rotation = (False, True, True)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'YXZ'
+    pbone.bone.layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['palm.04.L']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (True, True, True)
+    pbone.lock_rotation = (False, True, True)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'YXZ'
+    pbone.bone.layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['palm.01.R']]
+    pbone.rigify_type = 'palm'
+    pbone.lock_location = (False, False, False)
+    pbone.lock_rotation = (False, True, True)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'YXZ'
+    pbone.bone.layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone.rigify_parameters.add()
+    pbone = obj.pose.bones[bones['palm.02.R']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (False, False, False)
+    pbone.lock_rotation = (False, True, True)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'YXZ'
+    pbone.bone.layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['palm.03.R']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (False, False, False)
+    pbone.lock_rotation = (False, True, True)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'YXZ'
+    pbone.bone.layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['palm.04.R']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (False, False, False)
+    pbone.lock_rotation = (False, True, True)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'YXZ'
+    pbone.bone.layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['finger_index.01.L']]
+    pbone.rigify_type = 'finger'
+    pbone.lock_location = (True, True, True)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone.rigify_parameters.add()
+    try:
+        pbone.rigify_parameters[0].separate_extra_layers = True
+    except AttributeError:
+        pass
+    try:
+        pbone.rigify_parameters[0].extra_layers = [False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    except AttributeError:
+        pass
+    pbone = obj.pose.bones[bones['thumb.01.L']]
+    pbone.rigify_type = 'finger'
+    pbone.lock_location = (True, True, True)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone.rigify_parameters.add()
+    try:
+        pbone.rigify_parameters[0].extra_layers = [False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    except AttributeError:
+        pass
+    try:
+        pbone.rigify_parameters[0].separate_extra_layers = True
+    except AttributeError:
+        pass
+    pbone = obj.pose.bones[bones['finger_middle.01.L']]
+    pbone.rigify_type = 'finger'
+    pbone.lock_location = (True, True, True)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone.rigify_parameters.add()
+    try:
+        pbone.rigify_parameters[0].separate_extra_layers = True
+    except AttributeError:
+        pass
+    try:
+        pbone.rigify_parameters[0].extra_layers = [False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    except AttributeError:
+        pass
+    pbone = obj.pose.bones[bones['finger_ring.01.L']]
+    pbone.rigify_type = 'finger'
+    pbone.lock_location = (True, True, True)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone.rigify_parameters.add()
+    try:
+        pbone.rigify_parameters[0].separate_extra_layers = True
+    except AttributeError:
+        pass
+    try:
+        pbone.rigify_parameters[0].extra_layers = [False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    except AttributeError:
+        pass
+    pbone = obj.pose.bones[bones['finger_pinky.01.L']]
+    pbone.rigify_type = 'finger'
+    pbone.lock_location = (True, True, True)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone.rigify_parameters.add()
+    try:
+        pbone.rigify_parameters[0].separate_extra_layers = True
+    except AttributeError:
+        pass
+    try:
+        pbone.rigify_parameters[0].extra_layers = [False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    except AttributeError:
+        pass
+    pbone = obj.pose.bones[bones['finger_index.01.R']]
+    pbone.rigify_type = 'finger'
+    pbone.lock_location = (True, True, True)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone.rigify_parameters.add()
+    try:
+        pbone.rigify_parameters[0].extra_layers = [False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    except AttributeError:
+        pass
+    try:
+        pbone.rigify_parameters[0].separate_extra_layers = True
+    except AttributeError:
+        pass
+    pbone = obj.pose.bones[bones['thumb.01.R']]
+    pbone.rigify_type = 'finger'
+    pbone.lock_location = (True, True, True)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone.rigify_parameters.add()
+    try:
+        pbone.rigify_parameters[0].separate_extra_layers = True
+    except AttributeError:
+        pass
+    try:
+        pbone.rigify_parameters[0].extra_layers = [False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    except AttributeError:
+        pass
+    pbone = obj.pose.bones[bones['finger_middle.01.R']]
+    pbone.rigify_type = 'finger'
+    pbone.lock_location = (True, True, True)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone.rigify_parameters.add()
+    try:
+        pbone.rigify_parameters[0].separate_extra_layers = True
+    except AttributeError:
+        pass
+    try:
+        pbone.rigify_parameters[0].extra_layers = [False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    except AttributeError:
+        pass
+    pbone = obj.pose.bones[bones['finger_ring.01.R']]
+    pbone.rigify_type = 'finger'
+    pbone.lock_location = (True, True, True)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone.rigify_parameters.add()
+    try:
+        pbone.rigify_parameters[0].separate_extra_layers = True
+    except AttributeError:
+        pass
+    try:
+        pbone.rigify_parameters[0].extra_layers = [False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    except AttributeError:
+        pass
+    pbone = obj.pose.bones[bones['finger_pinky.01.R']]
+    pbone.rigify_type = 'finger'
+    pbone.lock_location = (True, True, True)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone.rigify_parameters.add()
+    try:
+        pbone.rigify_parameters[0].separate_extra_layers = True
+    except AttributeError:
+        pass
+    try:
+        pbone.rigify_parameters[0].extra_layers = [False, False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    except AttributeError:
+        pass
+    pbone = obj.pose.bones[bones['finger_index.02.L']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (False, False, False)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['thumb.02.L']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (False, False, False)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['finger_middle.02.L']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (False, False, False)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['finger_ring.02.L']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (False, False, False)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['finger_pinky.02.L']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (False, False, False)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['finger_index.02.R']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (False, False, False)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['thumb.02.R']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (False, False, False)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['finger_middle.02.R']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (False, False, False)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['finger_ring.02.R']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (False, False, False)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['finger_pinky.02.R']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (False, False, False)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['finger_index.03.L']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (False, False, False)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['thumb.03.L']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (False, False, False)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['finger_middle.03.L']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (False, False, False)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['finger_ring.03.L']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (False, False, False)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['finger_pinky.03.L']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (False, False, False)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['finger_index.03.R']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (False, False, False)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['thumb.03.R']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (False, False, False)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['finger_middle.03.R']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (False, False, False)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['finger_ring.03.R']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (False, False, False)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+    pbone = obj.pose.bones[bones['finger_pinky.03.R']]
+    pbone.rigify_type = ''
+    pbone.lock_location = (False, False, False)
+    pbone.lock_rotation = (False, False, False)
+    pbone.lock_rotation_w = False
+    pbone.lock_scale = (False, False, False)
+    pbone.rotation_mode = 'QUATERNION'
+    pbone.bone.layers = [False, False, False, False, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
+
+    bpy.ops.object.mode_set(mode='EDIT')
+    for bone in arm.edit_bones:
+        bone.select = False
+        bone.select_head = False
+        bone.select_tail = False
+    for b in bones:
+        bone = arm.edit_bones[bones[b]]
+        bone.select = True
+        bone.select_head = True
+        bone.select_tail = True
+        arm.edit_bones.active = bone
+
+    arm.layers = [(x in [0, 2, 4, 6, 8, 10, 12]) for x in range(0, 32)]
+
diff --git a/rigify/rig_ui_template.py b/rigify/rig_ui_template.py
new file mode 100644
index 0000000000000000000000000000000000000000..82d853a4a5b9bad1ba46562cf4495c94f8a25b55
--- /dev/null
+++ b/rigify/rig_ui_template.py
@@ -0,0 +1,96 @@
+#====================== BEGIN GPL LICENSE BLOCK ======================
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software Foundation,
+#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+#======================= END GPL LICENSE BLOCK ========================
+
+UI_SLIDERS = """
+import bpy
+
+rig_id = "%s"
+
+
+class RigUI(bpy.types.Panel):
+    bl_space_type = 'VIEW_3D'
+    bl_region_type = 'UI'
+    bl_label = "Rig Main Properties"
+    bl_idname = rig_id + "_PT_rig_ui"
+
+    @classmethod
+    def poll(self, context):
+        if context.mode != 'POSE':
+            return False
+        try:
+            return (context.active_object.data.get("rig_id") == rig_id)
+        except (AttributeError, KeyError, TypeError):
+            return False
+
+    def draw(self, context):
+        layout = self.layout
+        pose_bones = context.active_object.pose.bones
+        try:
+            selected_bones = [bone.name for bone in context.selected_pose_bones]
+            selected_bones += [context.active_pose_bone.name]
+        except (AttributeError, TypeError):
+            return
+
+        def is_selected(names):
+            # Returns whether any of the named bones are selected.
+            if type(names) == list:
+                for name in names:
+                    if name in selected_bones:
+                        return True
+            elif names in selected_bones:
+                return True
+            return False
+
+
+"""
+
+
+def layers_ui(layers):
+    """ Turn a list of booleans into a layer UI.
+    """
+
+    code = """
+class RigLayers(bpy.types.Panel):
+    bl_space_type = 'VIEW_3D'
+    bl_region_type = 'UI'
+    bl_label = "Rig Layers"
+    bl_idname = rig_id + "_PT_rig_layers"
+
+    @classmethod
+    def poll(self, context):
+        try:
+            return (context.active_object.data.get("rig_id") == rig_id)
+        except (AttributeError, KeyError, TypeError):
+            return False
+
+    def draw(self, context):
+        layout = self.layout
+        col = layout.column()
+"""
+    i = 0
+    for layer in layers:
+        if layer:
+            code += "\n        row = col.row()\n"
+            if i == 28:
+                code += "        row.prop(context.active_object.data, 'layers', index=%s, toggle=True, text='Root')\n" % (str(i))
+            else:
+                code += "        row.prop(context.active_object.data, 'layers', index=%s, toggle=True, text='%s')\n" % (str(i), str(i + 1))
+        i += 1
+
+    return code
+
diff --git a/rigify/rigs/__init__.py b/rigify/rigs/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/rigify/rigs/biped/__init__.py b/rigify/rigs/biped/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/rigify/rigs/biped/arm/__init__.py b/rigify/rigs/biped/arm/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..4198345bcf03b3fac36e837a649901c0d85a8636
--- /dev/null
+++ b/rigify/rigs/biped/arm/__init__.py
@@ -0,0 +1,209 @@
+#====================== BEGIN GPL LICENSE BLOCK ======================
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software Foundation,
+#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+#======================= END GPL LICENSE BLOCK ========================
+
+import bpy
+from imp import reload
+from . import fk, ik, deform
+from rigify.utils import MetarigError, get_layers
+
+reload(fk)
+reload(ik)
+reload(deform)
+
+script = """
+fk_arm = ["%s", "%s", "%s"]
+ik_arm = ["%s", "%s"]
+if is_selected(fk_arm+ik_arm):
+    layout.prop(pose_bones[ik_arm[0]], '["ikfk_switch"]', text="FK / IK (" + ik_arm[0] + ")", slider=True)
+if is_selected(fk_arm):
+    layout.prop(pose_bones[fk_arm[0]], '["isolate"]', text="Isolate Rotation (" + fk_arm[0] + ")", slider=True)
+"""
+
+
+class Rig:
+    """ An arm rig, with IK/FK switching and hinge switch.
+
+    """
+    def __init__(self, obj, bone, params):
+        """ Gather and validate data about the rig.
+            Store any data or references to data that will be needed later on.
+            In particular, store names of bones that will be needed.
+            Do NOT change any data in the scene.  This is a gathering phase only.
+
+        """
+        # Gather deform rig
+        self.deform_rig = deform.Rig(obj, bone, params)
+
+        # Gather FK rig
+        self.fk_rig = fk.Rig(obj, bone, params)
+
+        # Gather IK rig
+        self.ik_rig = ik.Rig(obj, bone, params, ikfk_switch=True)
+
+    def generate(self):
+        """ Generate the rig.
+            Do NOT modify any of the original bones, except for adding constraints.
+            The main armature should be selected and active before this is called.
+
+        """
+        self.deform_rig.generate()
+        fk_controls = self.fk_rig.generate()
+        ik_controls = self.ik_rig.generate()
+        return [script % (fk_controls[0], fk_controls[1], fk_controls[2], ik_controls[0], ik_controls[1])]
+
+    @classmethod
+    def add_parameters(self, group):
+        """ Add the parameters of this rig type to the
+            RigifyParameters IDPropertyGroup
+
+        """
+        items = [('X', 'X', ''), ('Y', 'Y', ''), ('Z', 'Z', ''), ('-X', '-X', ''), ('-Y', '-Y', ''), ('-Z', '-Z', '')]
+        group.primary_rotation_axis = bpy.props.EnumProperty(items=items, name="Primary Rotation Axis", default='X')
+
+        group.separate_ik_layers = bpy.props.BoolProperty(name="Separate IK Control Layers:", default=False, description="Enable putting the ik controls on a separate layer from the fk controls.")
+        group.ik_layers = bpy.props.BoolVectorProperty(size=32, description="Layers for the ik controls to be on.")
+
+        group.use_upper_arm_twist = bpy.props.BoolProperty(name="Upper Arm Twist", default=True, description="Generate the dual-bone twist setup for the upper arm.")
+        group.use_forearm_twist = bpy.props.BoolProperty(name="Forearm Twist", default=True, description="Generate the dual-bone twist setup for the forearm.")
+
+    @classmethod
+    def parameters_ui(self, layout, obj, bone):
+        """ Create the ui for the rig parameters.
+
+        """
+        params = obj.pose.bones[bone].rigify_parameters[0]
+
+        r = layout.row()
+        r.prop(params, "separate_ik_layers")
+
+        r = layout.row()
+        r.active = params.separate_ik_layers
+
+        col = r.column(align=True)
+        row = col.row(align=True)
+        row.prop(params, "ik_layers", index=0, toggle=True, text="")
+        row.prop(params, "ik_layers", index=1, toggle=True, text="")
+        row.prop(params, "ik_layers", index=2, toggle=True, text="")
+        row.prop(params, "ik_layers", index=3, toggle=True, text="")
+        row.prop(params, "ik_layers", index=4, toggle=True, text="")
+        row.prop(params, "ik_layers", index=5, toggle=True, text="")
+        row.prop(params, "ik_layers", index=6, toggle=True, text="")
+        row.prop(params, "ik_layers", index=7, toggle=True, text="")
+        row = col.row(align=True)
+        row.prop(params, "ik_layers", index=16, toggle=True, text="")
+        row.prop(params, "ik_layers", index=17, toggle=True, text="")
+        row.prop(params, "ik_layers", index=18, toggle=True, text="")
+        row.prop(params, "ik_layers", index=19, toggle=True, text="")
+        row.prop(params, "ik_layers", index=20, toggle=True, text="")
+        row.prop(params, "ik_layers", index=21, toggle=True, text="")
+        row.prop(params, "ik_layers", index=22, toggle=True, text="")
+        row.prop(params, "ik_layers", index=23, toggle=True, text="")
+
+        col = r.column(align=True)
+        row = col.row(align=True)
+        row.prop(params, "ik_layers", index=8, toggle=True, text="")
+        row.prop(params, "ik_layers", index=9, toggle=True, text="")
+        row.prop(params, "ik_layers", index=10, toggle=True, text="")
+        row.prop(params, "ik_layers", index=11, toggle=True, text="")
+        row.prop(params, "ik_layers", index=12, toggle=True, text="")
+        row.prop(params, "ik_layers", index=13, toggle=True, text="")
+        row.prop(params, "ik_layers", index=14, toggle=True, text="")
+        row.prop(params, "ik_layers", index=15, toggle=True, text="")
+        row = col.row(align=True)
+        row.prop(params, "ik_layers", index=24, toggle=True, text="")
+        row.prop(params, "ik_layers", index=25, toggle=True, text="")
+        row.prop(params, "ik_layers", index=26, toggle=True, text="")
+        row.prop(params, "ik_layers", index=27, toggle=True, text="")
+        row.prop(params, "ik_layers", index=28, toggle=True, text="")
+        row.prop(params, "ik_layers", index=29, toggle=True, text="")
+        row.prop(params, "ik_layers", index=30, toggle=True, text="")
+        row.prop(params, "ik_layers", index=31, toggle=True, text="")
+
+        r = layout.row()
+        r.label(text="Elbow rotation axis:")
+        r.prop(params, "primary_rotation_axis", text="")
+
+        col = layout.column()
+        col.prop(params, "use_upper_arm_twist")
+        col.prop(params, "use_forearm_twist")
+
+    @classmethod
+    def create_sample(self, obj):
+        # generated by rigify.utils.write_meta_rig
+        bpy.ops.object.mode_set(mode='EDIT')
+        arm = obj.data
+
+        bones = {}
+
+        bone = arm.edit_bones.new('upper_arm')
+        bone.head[:] = 0.0000, 0.0000, 0.0000
+        bone.tail[:] = 0.3000, 0.0300, 0.0000
+        bone.roll = 1.5708
+        bone.use_connect = False
+        bones['upper_arm'] = bone.name
+        bone = arm.edit_bones.new('forearm')
+        bone.head[:] = 0.3000, 0.0300, 0.0000
+        bone.tail[:] = 0.6000, 0.0000, 0.0000
+        bone.roll = 1.5708
+        bone.use_connect = True
+        bone.parent = arm.edit_bones[bones['upper_arm']]
+        bones['forearm'] = bone.name
+        bone = arm.edit_bones.new('hand')
+        bone.head[:] = 0.6000, 0.0000, 0.0000
+        bone.tail[:] = 0.7000, 0.0000, 0.0000
+        bone.roll = 3.1416
+        bone.use_connect = True
+        bone.parent = arm.edit_bones[bones['forearm']]
+        bones['hand'] = bone.name
+
+        bpy.ops.object.mode_set(mode='OBJECT')
+        pbone = obj.pose.bones[bones['upper_arm']]
+        pbone.rigify_type = 'biped.arm'
+        pbone.lock_location = (True, True, True)
+        pbone.lock_rotation = (False, False, False)
+        pbone.lock_rotation_w = False
+        pbone.lock_scale = (False, False, False)
+        pbone.rotation_mode = 'QUATERNION'
+        pbone.rigify_parameters.add()
+        pbone = obj.pose.bones[bones['forearm']]
+        pbone.rigify_type = ''
+        pbone.lock_location = (False, False, False)
+        pbone.lock_rotation = (False, False, False)
+        pbone.lock_rotation_w = False
+        pbone.lock_scale = (False, False, False)
+        pbone.rotation_mode = 'QUATERNION'
+        pbone = obj.pose.bones[bones['hand']]
+        pbone.rigify_type = ''
+        pbone.lock_location = (False, False, False)
+        pbone.lock_rotation = (False, False, False)
+        pbone.lock_rotation_w = False
+        pbone.lock_scale = (False, False, False)
+        pbone.rotation_mode = 'QUATERNION'
+
+        bpy.ops.object.mode_set(mode='EDIT')
+        for bone in arm.edit_bones:
+            bone.select = False
+            bone.select_head = False
+            bone.select_tail = False
+        for b in bones:
+            bone = arm.edit_bones[bones[b]]
+            bone.select = True
+            bone.select_head = True
+            bone.select_tail = True
+            arm.edit_bones.active = bone
+
diff --git a/rigify/rigs/biped/arm/deform.py b/rigify/rigs/biped/arm/deform.py
new file mode 100644
index 0000000000000000000000000000000000000000..2a7b31091f1133516bcf78ba49b79e6457eba377
--- /dev/null
+++ b/rigify/rigs/biped/arm/deform.py
@@ -0,0 +1,230 @@
+#====================== BEGIN GPL LICENSE BLOCK ======================
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software Foundation,
+#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+#======================= END GPL LICENSE BLOCK ========================
+
+import bpy
+from math import acos, degrees
+from mathutils import Vector, Matrix
+from rigify.utils import MetarigError
+from rigify.utils import copy_bone, flip_bone, put_bone
+from rigify.utils import connected_children_names
+from rigify.utils import strip_org, make_mechanism_name, make_deformer_name
+
+
+def align_roll(obj, bone1, bone2):
+    bone1_e = obj.data.edit_bones[bone1]
+    bone2_e = obj.data.edit_bones[bone2]
+
+    bone1_e.roll = 0.0
+
+    # Get the directions the bones are pointing in, as vectors
+    y1 = bone1_e.y_axis
+    x1 = bone1_e.x_axis
+    y2 = bone2_e.y_axis
+    x2 = bone2_e.x_axis
+
+    # Get the shortest axis to rotate bone1 on to point in the same direction as bone2
+    axis = y1.cross(y2)
+    axis.normalize()
+
+    # Angle to rotate on that shortest axis
+    angle = y1.angle(y2)
+
+    # Create rotation matrix to make bone1 point in the same direction as bone2
+    rot_mat = Matrix.Rotation(angle, 3, axis)
+
+    # Roll factor
+    x3 = x1 * rot_mat
+    dot = x2 * x3
+    if dot > 1.0:
+        dot = 1.0
+    elif dot < -1.0:
+        dot = -1.0
+    roll = acos(dot)
+
+    # Set the roll
+    bone1_e.roll = roll
+
+    # Check if we rolled in the right direction
+    x3 = bone1_e.x_axis * rot_mat
+    check = x2 * x3
+
+    # If not, reverse
+    if check < 0.9999:
+        bone1_e.roll = -roll
+
+
+class Rig:
+    """ An FK arm rig, with hinge switch.
+
+    """
+    def __init__(self, obj, bone, params):
+        """ Gather and validate data about the rig.
+            Store any data or references to data that will be needed later on.
+            In particular, store references to bones that will be needed, and
+            store names of bones that will be needed.
+            Do NOT change any data in the scene.  This is a gathering phase only.
+
+        """
+        self.obj = obj
+        self.params = params
+
+        # Get the chain of 3 connected bones
+        self.org_bones = [bone] + connected_children_names(self.obj, bone)[:2]
+
+        if len(self.org_bones) != 3:
+            raise MetarigError("RIGIFY ERROR: Bone '%s': input to rig type must be a chain of 3 bones." % (strip_org(bone)))
+
+        # Get rig parameters
+        self.use_upper_arm_twist = params.use_upper_arm_twist
+        self.use_forearm_twist = params.use_forearm_twist
+
+    def generate(self):
+        """ Generate the rig.
+            Do NOT modify any of the original bones, except for adding constraints.
+            The main armature should be selected and active before this is called.
+
+        """
+        bpy.ops.object.mode_set(mode='EDIT')
+
+        # Create upper arm bones
+        if self.use_upper_arm_twist:
+            uarm1 = copy_bone(self.obj, self.org_bones[0], make_deformer_name(strip_org(self.org_bones[0] + ".01")))
+            uarm2 = copy_bone(self.obj, self.org_bones[0], make_deformer_name(strip_org(self.org_bones[0] + ".02")))
+            utip = copy_bone(self.obj, self.org_bones[0], make_mechanism_name(strip_org(self.org_bones[0] + ".tip")))
+        else:
+            uarm = copy_bone(self.obj, self.org_bones[0], make_deformer_name(strip_org(self.org_bones[0])))
+
+        # Create forearm bones
+        if self.use_forearm_twist:
+            farm1 = copy_bone(self.obj, self.org_bones[1], make_deformer_name(strip_org(self.org_bones[1] + ".01")))
+            farm2 = copy_bone(self.obj, self.org_bones[1], make_deformer_name(strip_org(self.org_bones[1] + ".02")))
+            ftip = copy_bone(self.obj, self.org_bones[1], make_mechanism_name(strip_org(self.org_bones[1] + ".tip")))
+        else:
+            farm = copy_bone(self.obj, self.org_bones[1], make_deformer_name(strip_org(self.org_bones[1])))
+
+        # Create hand bone
+        hand = copy_bone(self.obj, self.org_bones[2], make_deformer_name(strip_org(self.org_bones[2])))
+
+        # Get edit bones
+        eb = self.obj.data.edit_bones
+
+        org_uarm_e = eb[self.org_bones[0]]
+        if self.use_upper_arm_twist:
+            uarm1_e = eb[uarm1]
+            uarm2_e = eb[uarm2]
+            utip_e = eb[utip]
+        else:
+            uarm_e = eb[uarm]
+
+        org_farm_e = eb[self.org_bones[1]]
+        if self.use_forearm_twist:
+            farm1_e = eb[farm1]
+            farm2_e = eb[farm2]
+            ftip_e = eb[ftip]
+        else:
+            farm_e = eb[farm]
+
+        org_hand_e = eb[self.org_bones[2]]
+        hand_e = eb[hand]
+
+        # Parent and position upper arm bones
+        if self.use_upper_arm_twist:
+            uarm1_e.use_connect = False
+            uarm2_e.use_connect = False
+            utip_e.use_connect = False
+
+            uarm1_e.parent = org_uarm_e.parent
+            uarm2_e.parent = org_uarm_e
+            utip_e.parent = org_uarm_e
+
+            center = Vector((org_uarm_e.head + org_uarm_e.tail) / 2)
+
+            uarm1_e.tail = center
+            uarm2_e.head = center
+            put_bone(self.obj, utip, org_uarm_e.tail)
+            utip_e.length = org_uarm_e.length / 8
+        else:
+            uarm_e.use_connect = False
+            uarm_e.parent = org_uarm_e
+
+        # Parent and position forearm bones
+        if self.use_forearm_twist:
+            farm1_e.use_connect = False
+            farm2_e.use_connect = False
+            ftip_e.use_connect = False
+
+            farm1_e.parent = org_farm_e
+            farm2_e.parent = org_farm_e
+            ftip_e.parent = org_farm_e
+
+            center = Vector((org_farm_e.head + org_farm_e.tail) / 2)
+
+            farm1_e.tail = center
+            farm2_e.head = center
+            put_bone(self.obj, ftip, org_farm_e.tail)
+            ftip_e.length = org_farm_e.length / 8
+
+            # Align roll of farm2 with hand
+            align_roll(self.obj, farm2, hand)
+        else:
+            farm_e.use_connect = False
+            farm_e.parent = org_farm_e
+
+        # Parent hand
+        hand_e.use_connect = False
+        hand_e.parent = org_hand_e
+
+        # Object mode, get pose bones
+        bpy.ops.object.mode_set(mode='OBJECT')
+        pb = self.obj.pose.bones
+
+        if self.use_upper_arm_twist:
+            uarm1_p = pb[uarm1]
+        if self.use_forearm_twist:
+            farm2_p = pb[farm2]
+        hand_p = pb[hand]
+
+        # Upper arm constraints
+        if self.use_upper_arm_twist:
+            con = uarm1_p.constraints.new('COPY_LOCATION')
+            con.name = "copy_location"
+            con.target = self.obj
+            con.subtarget = self.org_bones[0]
+
+            con = uarm1_p.constraints.new('COPY_SCALE')
+            con.name = "copy_scale"
+            con.target = self.obj
+            con.subtarget = self.org_bones[0]
+
+            con = uarm1_p.constraints.new('DAMPED_TRACK')
+            con.name = "track_to"
+            con.target = self.obj
+            con.subtarget = utip
+
+        # Forearm constraints
+        if self.use_forearm_twist:
+            con = farm2_p.constraints.new('COPY_ROTATION')
+            con.name = "copy_rotation"
+            con.target = self.obj
+            con.subtarget = hand
+
+            con = farm2_p.constraints.new('DAMPED_TRACK')
+            con.name = "track_to"
+            con.target = self.obj
+            con.subtarget = ftip
+
diff --git a/rigify/rigs/biped/arm/fk.py b/rigify/rigs/biped/arm/fk.py
new file mode 100644
index 0000000000000000000000000000000000000000..20ba89f274990143f6a961e9687640d0c5d88f1c
--- /dev/null
+++ b/rigify/rigs/biped/arm/fk.py
@@ -0,0 +1,208 @@
+#====================== BEGIN GPL LICENSE BLOCK ======================
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software Foundation,
+#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+#======================= END GPL LICENSE BLOCK ========================
+
+import bpy
+import math
+from rigify.utils import MetarigError
+from rigify.utils import copy_bone, flip_bone, put_bone
+from rigify.utils import connected_children_names
+from rigify.utils import strip_org, make_mechanism_name, make_deformer_name
+from rigify.utils import get_layers
+from rigify.utils import create_widget, create_limb_widget
+from rna_prop_ui import rna_idprop_ui_prop_get
+
+
+class Rig:
+    """ An FK arm rig, with hinge switch.
+
+    """
+    def __init__(self, obj, bone, params):
+        """ Gather and validate data about the rig.
+            Store any data or references to data that will be needed later on.
+            In particular, store references to bones that will be needed, and
+            store names of bones that will be needed.
+            Do NOT change any data in the scene.  This is a gathering phase only.
+
+        """
+        self.obj = obj
+        self.params = params
+
+        # Get the chain of 3 connected bones
+        self.org_bones = [bone] + connected_children_names(self.obj, bone)[:2]
+
+        if len(self.org_bones) != 3:
+            raise MetarigError("RIGIFY ERROR: Bone '%s': input to rig type must be a chain of 3 bones." % (strip_org(bone)))
+
+        # Get (optional) parent
+        if self.obj.data.bones[bone].parent == None:
+            self.org_parent = None
+        else:
+            self.org_parent = self.obj.data.bones[bone].parent.name
+
+        # Get the rig parameters
+        if "layers" in params:
+            self.layers = get_layers(params["layers"])
+        else:
+            self.layers = None
+
+        self.primary_rotation_axis = params.primary_rotation_axis
+
+    def generate(self):
+        """ Generate the rig.
+            Do NOT modify any of the original bones, except for adding constraints.
+            The main armature should be selected and active before this is called.
+
+        """
+        bpy.ops.object.mode_set(mode='EDIT')
+
+        # Create the control bones
+        uarm = copy_bone(self.obj, self.org_bones[0], strip_org(self.org_bones[0]))
+        farm = copy_bone(self.obj, self.org_bones[1], strip_org(self.org_bones[1]))
+        hand = copy_bone(self.obj, self.org_bones[2], strip_org(self.org_bones[2]))
+
+        # Create the hinge bones
+        if self.org_parent != None:
+            hinge = copy_bone(self.obj, self.org_parent, make_mechanism_name(uarm + ".hinge"))
+            socket1 = copy_bone(self.obj, uarm, make_mechanism_name(uarm + ".socket1"))
+            socket2 = copy_bone(self.obj, uarm, make_mechanism_name(uarm + ".socket2"))
+
+        # Get edit bones
+        eb = self.obj.data.edit_bones
+
+        uarm_e = eb[uarm]
+        farm_e = eb[farm]
+        hand_e = eb[hand]
+
+        if self.org_parent != None:
+            hinge_e = eb[hinge]
+            socket1_e = eb[socket1]
+            socket2_e = eb[socket2]
+
+        # Parenting
+        farm_e.parent = uarm_e
+        hand_e.parent = farm_e
+
+        if self.org_parent != None:
+            hinge_e.use_connect = False
+            socket1_e.use_connect = False
+            socket2_e.use_connect = False
+
+            uarm_e.parent = hinge_e
+            hinge_e.parent = socket2_e
+            socket2_e.parent = None
+
+        # Positioning
+        if self.org_parent != None:
+            center = (hinge_e.head + hinge_e.tail) / 2
+            hinge_e.head = center
+            socket1_e.length /= 4
+            socket2_e.length /= 3
+
+        # Object mode, get pose bones
+        bpy.ops.object.mode_set(mode='OBJECT')
+        pb = self.obj.pose.bones
+
+        uarm_p = pb[uarm]
+        farm_p = pb[farm]
+        hand_p = pb[hand]
+
+        if self.org_parent != None:
+            socket1_p = pb[socket1]
+            socket2_p = pb[socket2]
+
+        # Set the elbow to only bend on the x-axis.
+        farm_p.rotation_mode = 'XYZ'
+        if 'X' in self.primary_rotation_axis:
+            farm_p.lock_rotation = (False, True, True)
+        elif 'Y' in self.primary_rotation_axis:
+            farm_p.lock_rotation = (True, False, True)
+        else:
+            farm_p.lock_rotation = (True, True, False)
+
+        # Set up custom properties
+        if self.org_parent != None:
+            prop = rna_idprop_ui_prop_get(uarm_p, "isolate", create=True)
+            uarm_p["isolate"] = 0.0
+            prop["soft_min"] = prop["min"] = 0.0
+            prop["soft_max"] = prop["max"] = 1.0
+
+        # Hinge constraints / drivers
+        if self.org_parent != None:
+            con = socket2_p.constraints.new('COPY_LOCATION')
+            con.name = "copy_location"
+            con.target = self.obj
+            con.subtarget = socket1
+
+            con = socket2_p.constraints.new('COPY_TRANSFORMS')
+            con.name = "isolate_off"
+            con.target = self.obj
+            con.subtarget = socket1
+
+            # Driver
+            fcurve = con.driver_add("influence")
+            driver = fcurve.driver
+            var = driver.variables.new()
+            driver.type = 'AVERAGE'
+            var.name = "var"
+            var.targets[0].id_type = 'OBJECT'
+            var.targets[0].id = self.obj
+            var.targets[0].data_path = uarm_p.path_from_id() + '["isolate"]'
+            mod = fcurve.modifiers[0]
+            mod.poly_order = 1
+            mod.coefficients[0] = 1.0
+            mod.coefficients[1] = -1.0
+
+        # Constrain org bones to controls
+        con = pb[self.org_bones[0]].constraints.new('COPY_TRANSFORMS')
+        con.name = "fk"
+        con.target = self.obj
+        con.subtarget = uarm
+
+        con = pb[self.org_bones[1]].constraints.new('COPY_TRANSFORMS')
+        con.name = "fk"
+        con.target = self.obj
+        con.subtarget = farm
+
+        con = pb[self.org_bones[2]].constraints.new('COPY_TRANSFORMS')
+        con.name = "fk"
+        con.target = self.obj
+        con.subtarget = hand
+
+        # Set layers if specified
+        if self.layers:
+            uarm_p.bone.layers = self.layers
+            farm_p.bone.layers = self.layers
+            hand_p.bone.layers = self.layers
+
+        # Create control widgets
+        create_limb_widget(self.obj, uarm)
+        create_limb_widget(self.obj, farm)
+
+        ob = create_widget(self.obj, hand)
+        if ob != None:
+            verts = [(0.7, 1.5, 0.0), (0.7, -0.25, 0.0), (-0.7, -0.25, 0.0), (-0.7, 1.5, 0.0), (0.7, 0.723, 0.0), (-0.7, 0.723, 0.0), (0.7, 0.0, 0.0), (-0.7, 0.0, 0.0)]
+            edges = [(1, 2), (0, 3), (0, 4), (3, 5), (4, 6), (1, 6), (5, 7), (2, 7)]
+            mesh = ob.data
+            mesh.from_pydata(verts, edges, [])
+            mesh.update()
+
+            mod = ob.modifiers.new("subsurf", 'SUBSURF')
+            mod.levels = 2
+
+        return [uarm, farm, hand]
+
diff --git a/rigify/rigs/biped/arm/ik.py b/rigify/rigs/biped/arm/ik.py
new file mode 100644
index 0000000000000000000000000000000000000000..c341ede678222f3ee1f74c4d7145677c6895acb5
--- /dev/null
+++ b/rigify/rigs/biped/arm/ik.py
@@ -0,0 +1,281 @@
+#====================== BEGIN GPL LICENSE BLOCK ======================
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software Foundation,
+#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+#======================= END GPL LICENSE BLOCK ========================
+
+import bpy
+from mathutils import Vector
+from math import pi
+from rigify.utils import MetarigError
+from rigify.utils import copy_bone
+from rigify.utils import connected_children_names
+from rigify.utils import strip_org, make_mechanism_name, insert_before_lr
+from rigify.utils import get_layers
+from rigify.utils import create_widget, create_line_widget, create_sphere_widget
+from rna_prop_ui import rna_idprop_ui_prop_get
+
+
+class Rig:
+    """ An IK arm rig, with an optional ik/fk switch.
+
+    """
+    def __init__(self, obj, bone, params, ikfk_switch=False):
+        """ Gather and validate data about the rig.
+            Store any data or references to data that will be needed later on.
+            In particular, store references to bones that will be needed, and
+            store names of bones that will be needed.
+            Do NOT change any data in the scene.  This is a gathering phase only.
+
+            ikfk_switch: if True, create an ik/fk switch slider
+        """
+        self.obj = obj
+        self.params = params
+        self.switch = ikfk_switch
+
+        # Get the chain of 3 connected bones
+        self.org_bones = [bone] + connected_children_names(self.obj, bone)[:2]
+
+        if len(self.org_bones) != 3:
+            raise MetarigError("RIGIFY ERROR: Bone '%s': input to rig type must be a chain of 3 bones." % (strip_org(bone)))
+
+        # Get the rig parameters
+        if params.separate_ik_layers:
+            self.layers = list(params.ik_layers)
+        else:
+            self.layers = None
+
+        self.primary_rotation_axis = params.primary_rotation_axis
+
+    def generate(self):
+        """ Generate the rig.
+            Do NOT modify any of the original bones, except for adding constraints.
+            The main armature should be selected and active before this is called.
+
+        """
+        bpy.ops.object.mode_set(mode='EDIT')
+
+        # Create the bones
+        uarm = copy_bone(self.obj, self.org_bones[0], make_mechanism_name(strip_org(insert_before_lr(self.org_bones[0], "_ik"))))
+        farm = copy_bone(self.obj, self.org_bones[1], make_mechanism_name(strip_org(insert_before_lr(self.org_bones[1], "_ik"))))
+
+        hand = copy_bone(self.obj, self.org_bones[2], strip_org(insert_before_lr(self.org_bones[2], "_ik")))
+        pole = copy_bone(self.obj, self.org_bones[0], strip_org(insert_before_lr(self.org_bones[0], "_pole")))
+
+        vishand = copy_bone(self.obj, self.org_bones[2], "VIS-" + strip_org(insert_before_lr(self.org_bones[2], "_ik")))
+        vispole = copy_bone(self.obj, self.org_bones[1], "VIS-" + strip_org(insert_before_lr(self.org_bones[0], "_pole")))
+
+        # Get edit bones
+        eb = self.obj.data.edit_bones
+
+        uarm_e = eb[uarm]
+        farm_e = eb[farm]
+        hand_e = eb[hand]
+        pole_e = eb[pole]
+        vishand_e = eb[vishand]
+        vispole_e = eb[vispole]
+
+        # Parenting
+        farm_e.parent = uarm_e
+
+        hand_e.use_connect = False
+        hand_e.parent = None
+
+        pole_e.use_connect = False
+
+        vishand_e.use_connect = False
+        vishand_e.parent = None
+
+        vispole_e.use_connect = False
+        vispole_e.parent = None
+
+        # Misc
+        hand_e.use_local_location = False
+
+        vishand_e.hide_select = True
+        vispole_e.hide_select = True
+
+        # Positioning
+        v1 = farm_e.tail - uarm_e.head
+        if 'X' in self.primary_rotation_axis or 'Y' in self.primary_rotation_axis:
+            v2 = v1.cross(farm_e.x_axis)
+            if (v2 * farm_e.z_axis) > 0.0:
+                v2 *= -1.0
+        else:
+            v2 = v1.cross(farm_e.z_axis)
+            if (v2 * farm_e.x_axis) < 0.0:
+                v2 *= -1.0
+        v2.normalize()
+        v2 *= v1.length
+
+        if '-' in self.primary_rotation_axis:
+            v2 *= -1
+
+        pole_e.head = farm_e.head + v2
+        pole_e.tail = pole_e.head + (Vector((0, 1, 0)) * (v1.length / 8))
+        pole_e.roll = 0.0
+
+        vishand_e.tail = vishand_e.head + Vector((0, 0, v1.length / 32))
+        vispole_e.tail = vispole_e.head + Vector((0, 0, v1.length / 32))
+
+        # Object mode, get pose bones
+        bpy.ops.object.mode_set(mode='OBJECT')
+        pb = self.obj.pose.bones
+
+        uarm_p = pb[uarm]
+        farm_p = pb[farm]
+        hand_p = pb[hand]
+        pole_p = pb[pole]
+        vishand_p = pb[vishand]
+        vispole_p = pb[vispole]
+
+        # Set the elbow to only bend on the primary axis
+        if 'X' in self.primary_rotation_axis:
+            farm_p.lock_ik_y = True
+            farm_p.lock_ik_z = True
+        elif 'Y' in self.primary_rotation_axis:
+            farm_p.lock_ik_x = True
+            farm_p.lock_ik_z = True
+        else:
+            farm_p.lock_ik_x = True
+            farm_p.lock_ik_y = True
+
+        # Pole target only translates
+        pole_p.lock_location = False, False, False
+        pole_p.lock_rotation = True, True, True
+        pole_p.lock_rotation_w = True
+        pole_p.lock_scale = True, True, True
+
+        # Set up custom properties
+        if self.switch == True:
+            prop = rna_idprop_ui_prop_get(hand_p, "ikfk_switch", create=True)
+            hand_p["ikfk_switch"] = 0.0
+            prop["soft_min"] = prop["min"] = 0.0
+            prop["soft_max"] = prop["max"] = 1.0
+
+        # IK Constraint
+        con = farm_p.constraints.new('IK')
+        con.name = "ik"
+        con.target = self.obj
+        con.subtarget = hand
+        con.pole_target = self.obj
+        con.pole_subtarget = pole
+        if self.primary_rotation_axis == 'X' or self.primary_rotation_axis == 'Y':
+            con.pole_angle = -pi / 2
+        elif self.primary_rotation_axis == '-X' or self.primary_rotation_axis == '-Y':
+            con.pole_angle = pi / 2
+        elif self.primary_rotation_axis == 'Z':
+            con.pole_angle = 0.0
+        elif self.primary_rotation_axis == '-Z':
+            con.pole_angle = pi
+        con.chain_count = 2
+
+        # Constrain org bones to controls
+        con = pb[self.org_bones[0]].constraints.new('COPY_TRANSFORMS')
+        con.name = "ik"
+        con.target = self.obj
+        con.subtarget = uarm
+        if self.switch == True:
+            # IK/FK switch driver
+            fcurve = con.driver_add("influence")
+            driver = fcurve.driver
+            var = driver.variables.new()
+            driver.type = 'AVERAGE'
+            var.name = "var"
+            var.targets[0].id_type = 'OBJECT'
+            var.targets[0].id = self.obj
+            var.targets[0].data_path = hand_p.path_from_id() + '["ikfk_switch"]'
+
+        con = pb[self.org_bones[1]].constraints.new('COPY_TRANSFORMS')
+        con.name = "ik"
+        con.target = self.obj
+        con.subtarget = farm
+        if self.switch == True:
+            # IK/FK switch driver
+            fcurve = con.driver_add("influence")
+            driver = fcurve.driver
+            var = driver.variables.new()
+            driver.type = 'AVERAGE'
+            var.name = "var"
+            var.targets[0].id_type = 'OBJECT'
+            var.targets[0].id = self.obj
+            var.targets[0].data_path = hand_p.path_from_id() + '["ikfk_switch"]'
+
+        con = pb[self.org_bones[2]].constraints.new('COPY_TRANSFORMS')
+        con.name = "ik"
+        con.target = self.obj
+        con.subtarget = hand
+        if self.switch == True:
+            # IK/FK switch driver
+            fcurve = con.driver_add("influence")
+            driver = fcurve.driver
+            var = driver.variables.new()
+            driver.type = 'AVERAGE'
+            var.name = "var"
+            var.targets[0].id_type = 'OBJECT'
+            var.targets[0].id = self.obj
+            var.targets[0].data_path = hand_p.path_from_id() + '["ikfk_switch"]'
+
+        # VIS hand constraints
+        con = vishand_p.constraints.new('COPY_LOCATION')
+        con.name = "copy_loc"
+        con.target = self.obj
+        con.subtarget = self.org_bones[2]
+
+        con = vishand_p.constraints.new('STRETCH_TO')
+        con.name = "stretch_to"
+        con.target = self.obj
+        con.subtarget = hand
+        con.volume = 'NO_VOLUME'
+        con.rest_length = vishand_p.length
+
+        # VIS pole constraints
+        con = vispole_p.constraints.new('COPY_LOCATION')
+        con.name = "copy_loc"
+        con.target = self.obj
+        con.subtarget = self.org_bones[1]
+
+        con = vispole_p.constraints.new('STRETCH_TO')
+        con.name = "stretch_to"
+        con.target = self.obj
+        con.subtarget = pole
+        con.volume = 'NO_VOLUME'
+        con.rest_length = vispole_p.length
+
+        # Set layers if specified
+        if self.layers:
+            hand_p.bone.layers = self.layers
+            pole_p.bone.layers = self.layers
+            vishand_p.bone.layers = self.layers
+            vispole_p.bone.layers = self.layers
+
+        # Create widgets
+        create_line_widget(self.obj, vispole)
+        create_line_widget(self.obj, vishand)
+        create_sphere_widget(self.obj, pole)
+
+        ob = create_widget(self.obj, hand)
+        if ob != None:
+            verts = [(0.7, 1.5, 0.0), (0.7, -0.25, 0.0), (-0.7, -0.25, 0.0), (-0.7, 1.5, 0.0), (0.7, 0.723, 0.0), (-0.7, 0.723, 0.0), (0.7, 0.0, 0.0), (-0.7, 0.0, 0.0)]
+            edges = [(1, 2), (0, 3), (0, 4), (3, 5), (4, 6), (1, 6), (5, 7), (2, 7)]
+            mesh = ob.data
+            mesh.from_pydata(verts, edges, [])
+            mesh.update()
+
+            mod = ob.modifiers.new("subsurf", 'SUBSURF')
+            mod.levels = 2
+
+        return [hand, pole]
+
diff --git a/rigify/rigs/biped/leg/__init__.py b/rigify/rigs/biped/leg/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..ac8913f58f58dfbef36a0e2788bdd0cfed945d97
--- /dev/null
+++ b/rigify/rigs/biped/leg/__init__.py
@@ -0,0 +1,237 @@
+#====================== BEGIN GPL LICENSE BLOCK ======================
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software Foundation,
+#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+#======================= END GPL LICENSE BLOCK ========================
+
+import bpy
+from imp import reload
+from . import fk, ik, deform
+from rigify.utils import MetarigError, get_layers
+
+reload(fk)
+reload(ik)
+reload(deform)
+
+script = """
+fk_leg = ["%s", "%s", "%s"]
+ik_leg = ["%s", "%s", "%s"]
+if is_selected(fk_leg+ik_leg):
+    layout.prop(pose_bones[ik_leg[0]], '["ikfk_switch"]', text="FK / IK (" + ik_leg[0] + ")", slider=True)
+if is_selected(fk_leg):
+    layout.prop(pose_bones[fk_leg[0]], '["isolate"]', text="Isolate Rotation (" + fk_leg[0] + ")", slider=True)
+"""
+
+
+class Rig:
+    """ A leg rig, with IK/FK switching, a hinge switch, and foot roll.
+
+    """
+    def __init__(self, obj, bone, params):
+        """ Gather and validate data about the rig.
+            Store any data or references to data that will be needed later on.
+            In particular, store names of bones that will be needed.
+            Do NOT change any data in the scene.  This is a gathering phase only.
+
+        """
+        # Gather deform rig
+        self.deform_rig = deform.Rig(obj, bone, params)
+
+        # Gather FK rig
+        self.fk_rig = fk.Rig(obj, bone, params)
+
+        # Gather IK rig
+        self.ik_rig = ik.Rig(obj, bone, params, ikfk_switch=True)
+
+    def generate(self):
+        """ Generate the rig.
+            Do NOT modify any of the original bones, except for adding constraints.
+            The main armature should be selected and active before this is called.
+
+        """
+        self.deform_rig.generate()
+        fk_controls = self.fk_rig.generate()
+        ik_controls = self.ik_rig.generate()
+        return [script % (fk_controls[0], fk_controls[1], fk_controls[2], ik_controls[0], ik_controls[1], ik_controls[2])]
+
+    @classmethod
+    def add_parameters(self, group):
+        """ Add the parameters of this rig type to the
+            RigifyParameters IDPropertyGroup
+
+        """
+        items = [('X', 'X', ''), ('Y', 'Y', ''), ('Z', 'Z', ''), ('-X', '-X', ''), ('-Y', '-Y', ''), ('-Z', '-Z', '')]
+        group.primary_rotation_axis = bpy.props.EnumProperty(items=items, name="Primary Rotation Axis", default='X')
+
+        group.separate_ik_layers = bpy.props.BoolProperty(name="Separate IK Control Layers:", default=False, description="Enable putting the ik controls on a separate layer from the fk controls.")
+        group.ik_layers = bpy.props.BoolVectorProperty(size=32, description="Layers for the ik controls to be on.")
+
+        group.use_thigh_twist = bpy.props.BoolProperty(name="Thigh Twist", default=True, description="Generate the dual-bone twist setup for the thigh.")
+        group.use_shin_twist = bpy.props.BoolProperty(name="Shin Twist", default=True, description="Generate the dual-bone twist setup for the shin.")
+
+    @classmethod
+    def parameters_ui(self, layout, obj, bone):
+        """ Create the ui for the rig parameters.
+
+        """
+        params = obj.pose.bones[bone].rigify_parameters[0]
+
+        r = layout.row()
+        r.prop(params, "separate_ik_layers")
+
+        r = layout.row()
+        r.active = params.separate_ik_layers
+
+        col = r.column(align=True)
+        row = col.row(align=True)
+        row.prop(params, "ik_layers", index=0, toggle=True, text="")
+        row.prop(params, "ik_layers", index=1, toggle=True, text="")
+        row.prop(params, "ik_layers", index=2, toggle=True, text="")
+        row.prop(params, "ik_layers", index=3, toggle=True, text="")
+        row.prop(params, "ik_layers", index=4, toggle=True, text="")
+        row.prop(params, "ik_layers", index=5, toggle=True, text="")
+        row.prop(params, "ik_layers", index=6, toggle=True, text="")
+        row.prop(params, "ik_layers", index=7, toggle=True, text="")
+        row = col.row(align=True)
+        row.prop(params, "ik_layers", index=16, toggle=True, text="")
+        row.prop(params, "ik_layers", index=17, toggle=True, text="")
+        row.prop(params, "ik_layers", index=18, toggle=True, text="")
+        row.prop(params, "ik_layers", index=19, toggle=True, text="")
+        row.prop(params, "ik_layers", index=20, toggle=True, text="")
+        row.prop(params, "ik_layers", index=21, toggle=True, text="")
+        row.prop(params, "ik_layers", index=22, toggle=True, text="")
+        row.prop(params, "ik_layers", index=23, toggle=True, text="")
+
+        col = r.column(align=True)
+        row = col.row(align=True)
+        row.prop(params, "ik_layers", index=8, toggle=True, text="")
+        row.prop(params, "ik_layers", index=9, toggle=True, text="")
+        row.prop(params, "ik_layers", index=10, toggle=True, text="")
+        row.prop(params, "ik_layers", index=11, toggle=True, text="")
+        row.prop(params, "ik_layers", index=12, toggle=True, text="")
+        row.prop(params, "ik_layers", index=13, toggle=True, text="")
+        row.prop(params, "ik_layers", index=14, toggle=True, text="")
+        row.prop(params, "ik_layers", index=15, toggle=True, text="")
+        row = col.row(align=True)
+        row.prop(params, "ik_layers", index=24, toggle=True, text="")
+        row.prop(params, "ik_layers", index=25, toggle=True, text="")
+        row.prop(params, "ik_layers", index=26, toggle=True, text="")
+        row.prop(params, "ik_layers", index=27, toggle=True, text="")
+        row.prop(params, "ik_layers", index=28, toggle=True, text="")
+        row.prop(params, "ik_layers", index=29, toggle=True, text="")
+        row.prop(params, "ik_layers", index=30, toggle=True, text="")
+        row.prop(params, "ik_layers", index=31, toggle=True, text="")
+
+        r = layout.row()
+        r.label(text="Knee rotation axis:")
+        r.prop(params, "primary_rotation_axis", text="")
+
+        col = layout.column()
+        col.prop(params, "use_thigh_twist")
+        col.prop(params, "use_shin_twist")
+
+    @classmethod
+    def create_sample(self, obj):
+        # generated by rigify.utils.write_meta_rig
+        bpy.ops.object.mode_set(mode='EDIT')
+        arm = obj.data
+
+        bones = {}
+
+        bone = arm.edit_bones.new('thigh')
+        bone.head[:] = -0.0000, 0.0000, 1.0000
+        bone.tail[:] = -0.0000, -0.0500, 0.5000
+        bone.roll = -0.0000
+        bone.use_connect = False
+        bones['thigh'] = bone.name
+        bone = arm.edit_bones.new('shin')
+        bone.head[:] = -0.0000, -0.0500, 0.5000
+        bone.tail[:] = -0.0000, 0.0000, 0.1000
+        bone.roll = -0.0000
+        bone.use_connect = True
+        bone.parent = arm.edit_bones[bones['thigh']]
+        bones['shin'] = bone.name
+        bone = arm.edit_bones.new('foot')
+        bone.head[:] = -0.0000, 0.0000, 0.1000
+        bone.tail[:] = 0.0000, -0.1200, 0.0300
+        bone.roll = 0.0000
+        bone.use_connect = True
+        bone.parent = arm.edit_bones[bones['shin']]
+        bones['foot'] = bone.name
+        bone = arm.edit_bones.new('heel')
+        bone.head[:] = -0.0000, 0.0000, 0.1000
+        bone.tail[:] = -0.0000, 0.0600, 0.0000
+        bone.roll = -0.0000
+        bone.use_connect = True
+        bone.parent = arm.edit_bones[bones['shin']]
+        bones['heel'] = bone.name
+        bone = arm.edit_bones.new('toe')
+        bone.head[:] = 0.0000, -0.1200, 0.0300
+        bone.tail[:] = 0.0000, -0.2000, 0.0300
+        bone.roll = 3.1416
+        bone.use_connect = True
+        bone.parent = arm.edit_bones[bones['foot']]
+        bones['toe'] = bone.name
+
+        bpy.ops.object.mode_set(mode='OBJECT')
+        pbone = obj.pose.bones[bones['thigh']]
+        pbone.rigify_type = 'biped.leg'
+        pbone.lock_location = (True, True, True)
+        pbone.lock_rotation = (False, False, False)
+        pbone.lock_rotation_w = False
+        pbone.lock_scale = (False, False, False)
+        pbone.rotation_mode = 'QUATERNION'
+        pbone.rigify_parameters.add()
+        pbone = obj.pose.bones[bones['shin']]
+        pbone.rigify_type = ''
+        pbone.lock_location = (False, False, False)
+        pbone.lock_rotation = (False, False, False)
+        pbone.lock_rotation_w = False
+        pbone.lock_scale = (False, False, False)
+        pbone.rotation_mode = 'QUATERNION'
+        pbone = obj.pose.bones[bones['foot']]
+        pbone.rigify_type = ''
+        pbone.lock_location = (False, False, False)
+        pbone.lock_rotation = (False, False, False)
+        pbone.lock_rotation_w = False
+        pbone.lock_scale = (False, False, False)
+        pbone.rotation_mode = 'QUATERNION'
+        pbone = obj.pose.bones[bones['heel']]
+        pbone.rigify_type = ''
+        pbone.lock_location = (False, False, False)
+        pbone.lock_rotation = (False, False, False)
+        pbone.lock_rotation_w = False
+        pbone.lock_scale = (False, False, False)
+        pbone.rotation_mode = 'QUATERNION'
+        pbone = obj.pose.bones[bones['toe']]
+        pbone.rigify_type = ''
+        pbone.lock_location = (False, False, False)
+        pbone.lock_rotation = (False, False, False)
+        pbone.lock_rotation_w = False
+        pbone.lock_scale = (False, False, False)
+        pbone.rotation_mode = 'QUATERNION'
+
+        bpy.ops.object.mode_set(mode='EDIT')
+        for bone in arm.edit_bones:
+            bone.select = False
+            bone.select_head = False
+            bone.select_tail = False
+        for b in bones:
+            bone = arm.edit_bones[bones[b]]
+            bone.select = True
+            bone.select_head = True
+            bone.select_tail = True
+            arm.edit_bones.active = bone
+
diff --git a/rigify/rigs/biped/leg/deform.py b/rigify/rigs/biped/leg/deform.py
new file mode 100644
index 0000000000000000000000000000000000000000..df6c6a6041f2e220f15f118b00fc8aab9f71e49e
--- /dev/null
+++ b/rigify/rigs/biped/leg/deform.py
@@ -0,0 +1,264 @@
+#====================== BEGIN GPL LICENSE BLOCK ======================
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software Foundation,
+#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+#======================= END GPL LICENSE BLOCK ========================
+
+import bpy
+from math import acos, degrees
+from mathutils import Vector, Matrix
+from rigify.utils import MetarigError
+from rigify.utils import copy_bone, flip_bone, put_bone
+from rigify.utils import connected_children_names
+from rigify.utils import strip_org, make_mechanism_name, make_deformer_name
+
+
+def align_roll(obj, bone1, bone2):
+    bone1_e = obj.data.edit_bones[bone1]
+    bone2_e = obj.data.edit_bones[bone2]
+
+    bone1_e.roll = 0.0
+
+    # Get the directions the bones are pointing in, as vectors
+    y1 = bone1_e.y_axis
+    x1 = bone1_e.x_axis
+    y2 = bone2_e.y_axis
+    x2 = bone2_e.x_axis
+
+    # Get the shortest axis to rotate bone1 on to point in the same direction as bone2
+    axis = y1.cross(y2)
+    axis.normalize()
+
+    # Angle to rotate on that shortest axis
+    angle = y1.angle(y2)
+
+    # Create rotation matrix to make bone1 point in the same direction as bone2
+    rot_mat = Matrix.Rotation(angle, 3, axis)
+
+    # Roll factor
+    x3 = x1 * rot_mat
+    dot = x2 * x3
+    if dot > 1.0:
+        dot = 1.0
+    elif dot < -1.0:
+        dot = -1.0
+    roll = acos(dot)
+
+    # Set the roll
+    bone1_e.roll = roll
+
+    # Check if we rolled in the right direction
+    x3 = bone1_e.x_axis * rot_mat
+    check = x2 * x3
+
+    # If not, reverse
+    if check < 0.9999:
+        bone1_e.roll = -roll
+
+
+class Rig:
+    """ A leg deform-bone setup.
+
+    """
+    def __init__(self, obj, bone, params):
+        """ Gather and validate data about the rig.
+            Store any data or references to data that will be needed later on.
+            In particular, store references to bones that will be needed, and
+            store names of bones that will be needed.
+            Do NOT change any data in the scene.  This is a gathering phase only.
+
+        """
+        self.obj = obj
+        self.params = params
+
+        # Get the chain of 2 connected bones
+        leg_bones = [bone] + connected_children_names(self.obj, bone)[:2]
+
+        if len(leg_bones) != 2:
+            raise MetarigError("RIGIFY ERROR: Bone '%s': incorrect bone configuration for rig type." % (strip_org(bone)))
+
+        # Get the foot and heel
+        foot = None
+        heel = None
+        for b in self.obj.data.bones[leg_bones[1]].children:
+            if b.use_connect == True:
+                if len(b.children) == 0:
+                    heel = b.name
+                else:
+                    foot = b.name
+
+        if foot == None or heel == None:
+            raise MetarigError("RIGIFY ERROR: Bone '%s': incorrect bone configuration for rig type." % (strip_org(bone)))
+
+        # Get the toe
+        toe = None
+        for b in self.obj.data.bones[foot].children:
+            if b.use_connect == True:
+                toe = b.name
+
+        if toe == None:
+            raise MetarigError("RIGIFY ERROR: Bone '%s': incorrect bone configuration for rig type." % (strip_org(bone)))
+
+        self.org_bones = leg_bones + [foot, toe, heel]
+
+        # Get rig parameters
+        self.use_thigh_twist = params.use_thigh_twist
+        self.use_shin_twist = params.use_shin_twist
+
+    def generate(self):
+        """ Generate the rig.
+            Do NOT modify any of the original bones, except for adding constraints.
+            The main armature should be selected and active before this is called.
+
+        """
+        bpy.ops.object.mode_set(mode='EDIT')
+
+        # Create upper arm bones
+        if self.use_thigh_twist:
+            thigh1 = copy_bone(self.obj, self.org_bones[0], make_deformer_name(strip_org(self.org_bones[0] + ".01")))
+            thigh2 = copy_bone(self.obj, self.org_bones[0], make_deformer_name(strip_org(self.org_bones[0] + ".02")))
+            utip = copy_bone(self.obj, self.org_bones[0], make_mechanism_name(strip_org(self.org_bones[0] + ".tip")))
+        else:
+            thigh = copy_bone(self.obj, self.org_bones[0], make_deformer_name(strip_org(self.org_bones[0])))
+
+        # Create forearm bones
+        if self.use_shin_twist:
+            shin1 = copy_bone(self.obj, self.org_bones[1], make_deformer_name(strip_org(self.org_bones[1] + ".01")))
+            shin2 = copy_bone(self.obj, self.org_bones[1], make_deformer_name(strip_org(self.org_bones[1] + ".02")))
+            stip = copy_bone(self.obj, self.org_bones[1], make_mechanism_name(strip_org(self.org_bones[1] + ".tip")))
+        else:
+            shin = copy_bone(self.obj, self.org_bones[1], make_deformer_name(strip_org(self.org_bones[1])))
+
+        # Create foot bone
+        foot = copy_bone(self.obj, self.org_bones[2], make_deformer_name(strip_org(self.org_bones[2])))
+
+        # Create toe bone
+        toe = copy_bone(self.obj, self.org_bones[3], make_deformer_name(strip_org(self.org_bones[3])))
+
+        # Get edit bones
+        eb = self.obj.data.edit_bones
+
+        org_thigh_e = eb[self.org_bones[0]]
+        if self.use_thigh_twist:
+            thigh1_e = eb[thigh1]
+            thigh2_e = eb[thigh2]
+            utip_e = eb[utip]
+        else:
+            thigh_e = eb[thigh]
+
+        org_shin_e = eb[self.org_bones[1]]
+        if self.use_shin_twist:
+            shin1_e = eb[shin1]
+            shin2_e = eb[shin2]
+            stip_e = eb[stip]
+        else:
+            shin_e = eb[shin]
+
+        org_foot_e = eb[self.org_bones[2]]
+        foot_e = eb[foot]
+
+        org_toe_e = eb[self.org_bones[3]]
+        toe_e = eb[toe]
+
+        # Parent and position thigh bones
+        if self.use_thigh_twist:
+            thigh1_e.use_connect = False
+            thigh2_e.use_connect = False
+            utip_e.use_connect = False
+
+            thigh1_e.parent = org_thigh_e.parent
+            thigh2_e.parent = org_thigh_e
+            utip_e.parent = org_thigh_e
+
+            center = Vector((org_thigh_e.head + org_thigh_e.tail) / 2)
+
+            thigh1_e.tail = center
+            thigh2_e.head = center
+            put_bone(self.obj, utip, org_thigh_e.tail)
+            utip_e.length = org_thigh_e.length / 8
+        else:
+            thigh_e.use_connect = False
+            thigh_e.parent = org_thigh_e
+
+        # Parent and position shin bones
+        if self.use_shin_twist:
+            shin1_e.use_connect = False
+            shin2_e.use_connect = False
+            stip_e.use_connect = False
+
+            shin1_e.parent = org_shin_e
+            shin2_e.parent = org_shin_e
+            stip_e.parent = org_shin_e
+
+            center = Vector((org_shin_e.head + org_shin_e.tail) / 2)
+
+            shin1_e.tail = center
+            shin2_e.head = center
+            put_bone(self.obj, stip, org_shin_e.tail)
+            stip_e.length = org_shin_e.length / 8
+
+            # Align roll of shin2 with foot
+            align_roll(self.obj, shin2, foot)
+        else:
+            shin_e.use_connect = False
+            shin_e.parent = org_shin_e
+
+        # Parent foot
+        foot_e.use_connect = False
+        foot_e.parent = org_foot_e
+
+        # Parent toe
+        toe_e.use_connect = False
+        toe_e.parent = org_toe_e
+
+        # Object mode, get pose bones
+        bpy.ops.object.mode_set(mode='OBJECT')
+        pb = self.obj.pose.bones
+
+        if self.use_thigh_twist:
+            thigh1_p = pb[thigh1]
+        if self.use_shin_twist:
+            shin2_p = pb[shin2]
+        foot_p = pb[foot]
+
+        # Thigh constraints
+        if self.use_thigh_twist:
+            con = thigh1_p.constraints.new('COPY_LOCATION')
+            con.name = "copy_location"
+            con.target = self.obj
+            con.subtarget = self.org_bones[0]
+
+            con = thigh1_p.constraints.new('COPY_SCALE')
+            con.name = "copy_scale"
+            con.target = self.obj
+            con.subtarget = self.org_bones[0]
+
+            con = thigh1_p.constraints.new('DAMPED_TRACK')
+            con.name = "track_to"
+            con.target = self.obj
+            con.subtarget = utip
+
+        # Shin constraints
+        if self.use_shin_twist:
+            con = shin2_p.constraints.new('COPY_ROTATION')
+            con.name = "copy_rotation"
+            con.target = self.obj
+            con.subtarget = foot
+
+            con = shin2_p.constraints.new('DAMPED_TRACK')
+            con.name = "track_to"
+            con.target = self.obj
+            con.subtarget = stip
+
diff --git a/rigify/rigs/biped/leg/fk.py b/rigify/rigs/biped/leg/fk.py
new file mode 100644
index 0000000000000000000000000000000000000000..a212d44585b45e19fd0967e4e66992238d394d14
--- /dev/null
+++ b/rigify/rigs/biped/leg/fk.py
@@ -0,0 +1,246 @@
+#====================== BEGIN GPL LICENSE BLOCK ======================
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software Foundation,
+#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+#======================= END GPL LICENSE BLOCK ========================
+
+import bpy
+import math
+from mathutils import Vector
+from rigify.utils import MetarigError
+from rigify.utils import copy_bone, flip_bone, put_bone
+from rigify.utils import connected_children_names
+from rigify.utils import strip_org, make_mechanism_name, make_deformer_name
+from rigify.utils import get_layers
+from rigify.utils import create_widget, create_limb_widget
+from rna_prop_ui import rna_idprop_ui_prop_get
+
+
+class Rig:
+    """ An FK leg rig, with hinge switch.
+
+    """
+    def __init__(self, obj, bone, params):
+        """ Gather and validate data about the rig.
+            Store any data or references to data that will be needed later on.
+            In particular, store references to bones that will be needed, and
+            store names of bones that will be needed.
+            Do NOT change any data in the scene.  This is a gathering phase only.
+
+        """
+        self.obj = obj
+        self.params = params
+
+        # Get the chain of 2 connected bones
+        leg_bones = [bone] + connected_children_names(self.obj, bone)[:2]
+
+        if len(leg_bones) != 2:
+            raise MetarigError("RIGIFY ERROR: Bone '%s': incorrect bone configuration for rig type." % (strip_org(bone)))
+
+        # Get the foot and heel
+        foot = None
+        heel = None
+        for b in self.obj.data.bones[leg_bones[1]].children:
+            if b.use_connect == True:
+                if len(b.children) == 0:
+                    heel = b.name
+                else:
+                    foot = b.name
+
+        if foot == None or heel == None:
+            raise MetarigError("RIGIFY ERROR: Bone '%s': incorrect bone configuration for rig type." % (strip_org(bone)))
+
+        # Get the toe
+        toe = None
+        for b in self.obj.data.bones[foot].children:
+            if b.use_connect == True:
+                toe = b.name
+
+        # Get the toe
+        if toe == None:
+            raise MetarigError("RIGIFY ERROR: Bone '%s': incorrect bone configuration for rig type." % (strip_org(bone)))
+
+        self.org_bones = leg_bones + [foot, toe, heel]
+
+        # Get (optional) parent
+        if self.obj.data.bones[bone].parent == None:
+            self.org_parent = None
+        else:
+            self.org_parent = self.obj.data.bones[bone].parent.name
+
+        # Get rig parameters
+        if "layers" in params:
+            self.layers = get_layers(params["layers"])
+        else:
+            self.layers = None
+
+        self.primary_rotation_axis = params.primary_rotation_axis
+
+    def generate(self):
+        """ Generate the rig.
+            Do NOT modify any of the original bones, except for adding constraints.
+            The main armature should be selected and active before this is called.
+
+        """
+        bpy.ops.object.mode_set(mode='EDIT')
+
+        # Create the control bones
+        thigh = copy_bone(self.obj, self.org_bones[0], strip_org(self.org_bones[0]))
+        shin = copy_bone(self.obj, self.org_bones[1], strip_org(self.org_bones[1]))
+        foot = copy_bone(self.obj, self.org_bones[2], strip_org(self.org_bones[2]))
+
+        # Create the foot mechanism bone
+        foot_mch = copy_bone(self.obj, self.org_bones[2], make_mechanism_name(strip_org(self.org_bones[2])))
+
+        # Create the hinge bones
+        if self.org_parent != None:
+            hinge = copy_bone(self.obj, self.org_parent, make_mechanism_name(thigh + ".hinge"))
+            socket1 = copy_bone(self.obj, thigh, make_mechanism_name(thigh + ".socket1"))
+            socket2 = copy_bone(self.obj, thigh, make_mechanism_name(thigh + ".socket2"))
+
+        # Get edit bones
+        eb = self.obj.data.edit_bones
+
+        thigh_e = eb[thigh]
+        shin_e = eb[shin]
+        foot_e = eb[foot]
+        foot_mch_e = eb[foot_mch]
+
+        if self.org_parent != None:
+            hinge_e = eb[hinge]
+            socket1_e = eb[socket1]
+            socket2_e = eb[socket2]
+
+        # Parenting
+        shin_e.parent = thigh_e
+        foot_e.parent = shin_e
+
+        foot_mch_e.use_connect = False
+        foot_mch_e.parent = foot_e
+
+        if self.org_parent != None:
+            hinge_e.use_connect = False
+            socket1_e.use_connect = False
+            socket2_e.use_connect = False
+
+            thigh_e.parent = hinge_e
+            hinge_e.parent = socket2_e
+            socket2_e.parent = None
+
+        # Positioning
+        vec = Vector(eb[self.org_bones[3]].vector)
+        vec = vec.normalize()
+        foot_e.tail = foot_e.head + (vec * foot_e.length)
+        foot_e.roll = eb[self.org_bones[3]].roll
+
+        if self.org_parent != None:
+            center = (hinge_e.head + hinge_e.tail) / 2
+            hinge_e.head = center
+            socket1_e.length /= 4
+            socket2_e.length /= 3
+
+        # Object mode, get pose bones
+        bpy.ops.object.mode_set(mode='OBJECT')
+        pb = self.obj.pose.bones
+
+        thigh_p = pb[thigh]
+        shin_p = pb[shin]
+        foot_p = pb[foot]
+
+        if self.org_parent != None:
+            socket1_p = pb[socket1]
+            socket2_p = pb[socket2]
+
+        # Set the elbow to only bend on the x-axis.
+        shin_p.rotation_mode = 'XYZ'
+        if 'X' in self.primary_rotation_axis:
+            shin_p.lock_rotation = (False, True, True)
+        elif 'Y' in self.primary_rotation_axis:
+            shin_p.lock_rotation = (True, False, True)
+        else:
+            shin_p.lock_rotation = (True, True, False)
+
+        # Set up custom properties
+        if self.org_parent != None:
+            prop = rna_idprop_ui_prop_get(thigh_p, "isolate", create=True)
+            thigh_p["isolate"] = 0.0
+            prop["soft_min"] = prop["min"] = 0.0
+            prop["soft_max"] = prop["max"] = 1.0
+
+        # Hinge constraints / drivers
+        if self.org_parent != None:
+            con = socket2_p.constraints.new('COPY_LOCATION')
+            con.name = "copy_location"
+            con.target = self.obj
+            con.subtarget = socket1
+
+            con = socket2_p.constraints.new('COPY_TRANSFORMS')
+            con.name = "isolate_off"
+            con.target = self.obj
+            con.subtarget = socket1
+
+            # Driver
+            fcurve = con.driver_add("influence")
+            driver = fcurve.driver
+            var = driver.variables.new()
+            driver.type = 'AVERAGE'
+            var.name = "var"
+            var.targets[0].id_type = 'OBJECT'
+            var.targets[0].id = self.obj
+            var.targets[0].data_path = thigh_p.path_from_id() + '["isolate"]'
+            mod = fcurve.modifiers[0]
+            mod.poly_order = 1
+            mod.coefficients[0] = 1.0
+            mod.coefficients[1] = -1.0
+
+        # Constrain org bones to controls
+        con = pb[self.org_bones[0]].constraints.new('COPY_TRANSFORMS')
+        con.name = "fk"
+        con.target = self.obj
+        con.subtarget = thigh
+
+        con = pb[self.org_bones[1]].constraints.new('COPY_TRANSFORMS')
+        con.name = "fk"
+        con.target = self.obj
+        con.subtarget = shin
+
+        con = pb[self.org_bones[2]].constraints.new('COPY_TRANSFORMS')
+        con.name = "fk"
+        con.target = self.obj
+        con.subtarget = foot_mch
+
+        # Set layers if specified
+        if self.layers:
+            thigh_p.bone.layers = self.layers
+            shin_p.bone.layers = self.layers
+            foot_p.bone.layers = self.layers
+
+        # Create control widgets
+        create_limb_widget(self.obj, thigh)
+        create_limb_widget(self.obj, shin)
+
+        ob = create_widget(self.obj, foot)
+        if ob != None:
+            verts = [(0.7, 1.5, 0.0), (0.7, -0.25, 0.0), (-0.7, -0.25, 0.0), (-0.7, 1.5, 0.0), (0.7, 0.723, 0.0), (-0.7, 0.723, 0.0), (0.7, 0.0, 0.0), (-0.7, 0.0, 0.0)]
+            edges = [(1, 2), (0, 3), (0, 4), (3, 5), (4, 6), (1, 6), (5, 7), (2, 7)]
+            mesh = ob.data
+            mesh.from_pydata(verts, edges, [])
+            mesh.update()
+
+            mod = ob.modifiers.new("subsurf", 'SUBSURF')
+            mod.levels = 2
+
+        return [thigh, shin, foot]
+
diff --git a/rigify/rigs/biped/leg/ik.py b/rigify/rigs/biped/leg/ik.py
new file mode 100644
index 0000000000000000000000000000000000000000..5697a2b6446315b264484afc0fd053070f9f3e3b
--- /dev/null
+++ b/rigify/rigs/biped/leg/ik.py
@@ -0,0 +1,499 @@
+#====================== BEGIN GPL LICENSE BLOCK ======================
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software Foundation,
+#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+#======================= END GPL LICENSE BLOCK ========================
+
+import bpy
+from mathutils import Vector
+from math import pi, acos
+from rigify.utils import MetarigError
+from rigify.utils import copy_bone, flip_bone, put_bone
+from rigify.utils import connected_children_names
+from rigify.utils import strip_org, make_mechanism_name, insert_before_lr
+from rigify.utils import get_layers
+from rigify.utils import create_widget, create_line_widget, create_sphere_widget, create_circle_widget
+from rna_prop_ui import rna_idprop_ui_prop_get
+
+
+def align_x_axis(obj, bone, vec):
+    """ Aligns the x-axis of a bone to the given vector.  This only works if it
+        can be an exact match.
+        Must be in edit mode.
+
+    """
+    vec.normalize()
+    bone_e = obj.data.edit_bones[bone]
+    dot = bone_e.x_axis.dot(vec)
+    if dot < -1:
+        dot = -1
+    elif dot > 1:
+        dot = 1
+
+    angle = acos(dot)
+
+    bone_e.roll += angle
+
+    dot1 = bone_e.x_axis.dot(vec)
+
+    bone_e.roll -= angle * 2
+
+    dot2 = bone_e.x_axis.dot(vec)
+
+    if dot1 > dot2:
+        bone_e.roll += angle * 2
+
+
+class Rig:
+    """ An IK leg rig, with an optional ik/fk switch.
+
+    """
+    def __init__(self, obj, bone, params, ikfk_switch=False):
+        """ Gather and validate data about the rig.
+            Store any data or references to data that will be needed later on.
+            In particular, store references to bones that will be needed, and
+            store names of bones that will be needed.
+            Do NOT change any data in the scene.  This is a gathering phase only.
+        """
+        self.obj = obj
+        self.params = params
+        self.switch = ikfk_switch
+
+        # Get the chain of 2 connected bones
+        leg_bones = [bone] + connected_children_names(self.obj, bone)[:2]
+
+        if len(leg_bones) != 2:
+            raise MetarigError("RIGIFY ERROR: Bone '%s': incorrect bone configuration for rig type." % (strip_org(bone)))
+
+        # Get the foot and heel
+        foot = None
+        heel = None
+        for b in self.obj.data.bones[leg_bones[1]].children:
+            if b.use_connect == True:
+                if len(b.children) == 0:
+                    heel = b.name
+                else:
+                    foot = b.name
+
+        if foot == None or heel == None:
+            raise MetarigError("RIGIFY ERROR: Bone '%s': incorrect bone configuration for rig type." % (strip_org(bone)))
+
+        # Get the toe
+        toe = None
+        for b in self.obj.data.bones[foot].children:
+            if b.use_connect == True:
+                toe = b.name
+
+        # Get toe
+        if toe == None:
+            raise MetarigError("RIGIFY ERROR: Bone '%s': incorrect bone configuration for rig type." % (strip_org(bone)))
+
+        self.org_bones = leg_bones + [foot, toe, heel]
+
+        # Get rig parameters
+        if params.separate_ik_layers:
+            self.layers = list(params.ik_layers)
+        else:
+            self.layers = None
+
+        self.primary_rotation_axis = params.primary_rotation_axis
+
+    def generate(self):
+        """ Generate the rig.
+            Do NOT modify any of the original bones, except for adding constraints.
+            The main armature should be selected and active before this is called.
+
+        """
+        bpy.ops.object.mode_set(mode='EDIT')
+
+        # Create the bones
+        thigh = copy_bone(self.obj, self.org_bones[0], make_mechanism_name(strip_org(insert_before_lr(self.org_bones[0], "_ik"))))
+        shin = copy_bone(self.obj, self.org_bones[1], make_mechanism_name(strip_org(insert_before_lr(self.org_bones[1], "_ik"))))
+
+        foot = copy_bone(self.obj, self.org_bones[2], strip_org(insert_before_lr(self.org_bones[2], "_ik")))
+        foot_ik_target = copy_bone(self.obj, self.org_bones[2], make_mechanism_name(strip_org(insert_before_lr(self.org_bones[2], "_ik_target"))))
+        pole = copy_bone(self.obj, self.org_bones[0], strip_org(insert_before_lr(self.org_bones[0], "_pole")))
+
+        toe = copy_bone(self.obj, self.org_bones[3], strip_org(self.org_bones[3]))
+        toe_parent = copy_bone(self.obj, self.org_bones[2], make_mechanism_name(strip_org(self.org_bones[3] + ".parent")))
+        toe_parent_socket1 = copy_bone(self.obj, self.org_bones[2], make_mechanism_name(strip_org(self.org_bones[3] + ".socket1")))
+        toe_parent_socket2 = copy_bone(self.obj, self.org_bones[2], make_mechanism_name(strip_org(self.org_bones[3] + ".socket2")))
+
+        foot_roll = copy_bone(self.obj, self.org_bones[4], strip_org(insert_before_lr(self.org_bones[2], "_roll")))
+        roll1 = copy_bone(self.obj, self.org_bones[4], make_mechanism_name(strip_org(self.org_bones[2] + ".roll")))
+        roll2 = copy_bone(self.obj, self.org_bones[4], make_mechanism_name(strip_org(self.org_bones[2] + ".roll")))
+
+        visfoot = copy_bone(self.obj, self.org_bones[2], "VIS-" + strip_org(insert_before_lr(self.org_bones[2], "_ik")))
+        vispole = copy_bone(self.obj, self.org_bones[1], "VIS-" + strip_org(insert_before_lr(self.org_bones[0], "_pole")))
+
+        # Get edit bones
+        eb = self.obj.data.edit_bones
+
+        org_foot_e = eb[self.org_bones[2]]
+        thigh_e = eb[thigh]
+        shin_e = eb[shin]
+        foot_e = eb[foot]
+        foot_ik_target_e = eb[foot_ik_target]
+        pole_e = eb[pole]
+        toe_e = eb[toe]
+        toe_parent_e = eb[toe_parent]
+        toe_parent_socket1_e = eb[toe_parent_socket1]
+        toe_parent_socket2_e = eb[toe_parent_socket2]
+        foot_roll_e = eb[foot_roll]
+        roll1_e = eb[roll1]
+        roll2_e = eb[roll2]
+        visfoot_e = eb[visfoot]
+        vispole_e = eb[vispole]
+
+        # Parenting
+        shin_e.parent = thigh_e
+
+        foot_e.use_connect = False
+        foot_e.parent = None
+        foot_ik_target_e.use_connect = False
+        foot_ik_target_e.parent = roll2_e
+
+        pole_e.use_connect = False
+        pole_e.parent = foot_e
+
+        toe_e.parent = toe_parent_e
+        toe_parent_e.use_connect = False
+        toe_parent_e.parent = toe_parent_socket1_e
+        toe_parent_socket1_e.use_connect = False
+        toe_parent_socket1_e.parent = roll1_e
+        toe_parent_socket2_e.use_connect = False
+        toe_parent_socket2_e.parent = eb[self.org_bones[2]]
+
+        foot_roll_e.use_connect = False
+        foot_roll_e.parent = foot_e
+
+        roll1_e.use_connect = False
+        roll1_e.parent = foot_e
+
+        roll2_e.use_connect = False
+        roll2_e.parent = roll1_e
+
+        visfoot_e.use_connect = False
+        visfoot_e.parent = None
+
+        vispole_e.use_connect = False
+        vispole_e.parent = None
+
+        # Misc
+        foot_e.use_local_location = False
+
+        visfoot_e.hide_select = True
+        vispole_e.hide_select = True
+
+        # Positioning
+        vec = Vector(toe_e.vector)
+        vec = vec.normalize()
+        foot_e.tail = foot_e.head + (vec * foot_e.length)
+        foot_e.roll = toe_e.roll
+
+        v1 = shin_e.tail - thigh_e.head
+
+        if 'X' in self.primary_rotation_axis or 'Y' in self.primary_rotation_axis:
+            v2 = v1.cross(shin_e.x_axis)
+            if (v2 * shin_e.z_axis) > 0.0:
+                v2 *= -1.0
+        else:
+            v2 = v1.cross(shin_e.z_axis)
+            if (v2 * shin_e.x_axis) < 0.0:
+                v2 *= -1.0
+        v2.normalize()
+        v2 *= v1.length
+
+        if '-' in self.primary_rotation_axis:
+            v2 *= -1
+
+        pole_e.head = shin_e.head + v2
+        pole_e.tail = pole_e.head + (Vector((0, 1, 0)) * (v1.length / 8))
+        pole_e.roll = 0.0
+
+        flip_bone(self.obj, toe_parent_socket1)
+        flip_bone(self.obj, toe_parent_socket2)
+        toe_parent_socket1_e.head = Vector(org_foot_e.tail)
+        toe_parent_socket2_e.head = Vector(org_foot_e.tail)
+        toe_parent_socket1_e.tail = Vector(org_foot_e.tail) + (Vector((0, 0, 1)) * foot_e.length / 2)
+        toe_parent_socket2_e.tail = Vector(org_foot_e.tail) + (Vector((0, 0, 1)) * foot_e.length / 3)
+        toe_parent_socket2_e.roll = toe_parent_socket1_e.roll
+
+        tail = Vector(roll1_e.tail)
+        roll1_e.tail = Vector(org_foot_e.tail)
+        roll1_e.tail = Vector(org_foot_e.tail)
+        roll1_e.head = tail
+        roll2_e.head = Vector(org_foot_e.tail)
+        foot_roll_e.head = Vector(org_foot_e.tail)
+        put_bone(self.obj, foot_roll, roll1_e.head)
+        foot_roll_e.length /= 2
+
+        roll_axis = roll1_e.vector.cross(org_foot_e.vector)
+        align_x_axis(self.obj, roll1, roll_axis)
+        align_x_axis(self.obj, roll2, roll_axis)
+        foot_roll_e.roll = roll2_e.roll
+
+        visfoot_e.tail = visfoot_e.head + Vector((0, 0, v1.length / 32))
+        vispole_e.tail = vispole_e.head + Vector((0, 0, v1.length / 32))
+
+        # Weird alignment issues.  Fix.
+        toe_parent_e.head = Vector(org_foot_e.head)
+        toe_parent_e.tail = Vector(org_foot_e.tail)
+        toe_parent_e.roll = org_foot_e.roll
+
+        foot_e.head = Vector(org_foot_e.head)
+
+        foot_ik_target_e.head = Vector(org_foot_e.head)
+        foot_ik_target_e.tail = Vector(org_foot_e.tail)
+
+        # Object mode, get pose bones
+        bpy.ops.object.mode_set(mode='OBJECT')
+        pb = self.obj.pose.bones
+
+        thigh_p = pb[thigh]
+        shin_p = pb[shin]
+        foot_p = pb[foot]
+        pole_p = pb[pole]
+        foot_roll_p = pb[foot_roll]
+        roll1_p = pb[roll1]
+        roll2_p = pb[roll2]
+        toe_p = pb[toe]
+        toe_parent_p = pb[toe_parent]
+        toe_parent_socket1_p = pb[toe_parent_socket1]
+        visfoot_p = pb[visfoot]
+        vispole_p = pb[vispole]
+
+        # Set the knee to only bend on the primary axis.
+        if 'X' in self.primary_rotation_axis:
+            shin_p.lock_ik_y = True
+            shin_p.lock_ik_z = True
+        elif 'Y' in self.primary_rotation_axis:
+            shin_p.lock_ik_x = True
+            shin_p.lock_ik_z = True
+        else:
+            shin_p.lock_ik_x = True
+            shin_p.lock_ik_y = True
+
+        # Foot roll control only rotates on x-axis.
+        foot_roll_p.rotation_mode = 'XYZ'
+        foot_roll_p.lock_rotation = False, True, True
+        foot_roll_p.lock_location = True, True, True
+        foot_roll_p.lock_scale = True, True, True
+
+        # Pole target only translates
+        pole_p.lock_location = False, False, False
+        pole_p.lock_rotation = True, True, True
+        pole_p.lock_rotation_w = True
+        pole_p.lock_scale = True, True, True
+
+        # Set up custom properties
+        if self.switch == True:
+            prop = rna_idprop_ui_prop_get(foot_p, "ikfk_switch", create=True)
+            foot_p["ikfk_switch"] = 0.0
+            prop["soft_min"] = prop["min"] = 0.0
+            prop["soft_max"] = prop["max"] = 1.0
+
+        # IK Constraint
+        con = shin_p.constraints.new('IK')
+        con.name = "ik"
+        con.target = self.obj
+        con.subtarget = foot_ik_target
+        con.pole_target = self.obj
+        con.pole_subtarget = pole
+        if self.primary_rotation_axis == 'X' or self.primary_rotation_axis == 'Y':
+            con.pole_angle = -pi / 2
+        elif self.primary_rotation_axis == '-X' or self.primary_rotation_axis == '-Y':
+            con.pole_angle = pi / 2
+        elif self.primary_rotation_axis == 'Z':
+            con.pole_angle = 0.0
+        elif self.primary_rotation_axis == '-Z':
+            con.pole_angle = pi
+        con.chain_count = 2
+
+        # toe_parent constraint
+        con = toe_parent_socket1_p.constraints.new('COPY_LOCATION')
+        con.name = "copy_location"
+        con.target = self.obj
+        con.subtarget = toe_parent_socket2
+
+        con = toe_parent_socket1_p.constraints.new('COPY_SCALE')
+        con.name = "copy_scale"
+        con.target = self.obj
+        con.subtarget = toe_parent_socket2
+
+        con = toe_parent_socket1_p.constraints.new('COPY_TRANSFORMS')  # drive with IK switch
+        con.name = "fk"
+        con.target = self.obj
+        con.subtarget = toe_parent_socket2
+
+        fcurve = con.driver_add("influence")
+        driver = fcurve.driver
+        var = driver.variables.new()
+        driver.type = 'AVERAGE'
+        var.name = "var"
+        var.targets[0].id_type = 'OBJECT'
+        var.targets[0].id = self.obj
+        var.targets[0].data_path = foot_p.path_from_id() + '["ikfk_switch"]'
+        mod = fcurve.modifiers[0]
+        mod.poly_order = 1
+        mod.coefficients[0] = 1.0
+        mod.coefficients[1] = -1.0
+
+        # Foot roll constraints
+        con = roll1_p.constraints.new('COPY_ROTATION')
+        con.name = "roll"
+        con.target = self.obj
+        con.subtarget = foot_roll
+        con.target_space = 'LOCAL'
+        con.owner_space = 'LOCAL'
+
+        con = roll1_p.constraints.new('LIMIT_ROTATION')
+        con.name = "limit_roll"
+        con.use_limit_x = True
+        con.min_x = -180
+        con.max_x = 0
+        con.owner_space = 'LOCAL'
+
+        con = roll2_p.constraints.new('COPY_ROTATION')
+        con.name = "roll"
+        con.target = self.obj
+        con.subtarget = foot_roll
+        con.target_space = 'LOCAL'
+        con.owner_space = 'LOCAL'
+
+        con = roll2_p.constraints.new('LIMIT_ROTATION')
+        con.name = "limit_roll"
+        con.use_limit_x = True
+        con.min_x = 0
+        con.max_x = 180
+        con.owner_space = 'LOCAL'
+
+        # Constrain org bones to controls
+        con = pb[self.org_bones[0]].constraints.new('COPY_TRANSFORMS')
+        con.name = "ik"
+        con.target = self.obj
+        con.subtarget = thigh
+        if self.switch == True:
+            # IK/FK switch driver
+            fcurve = con.driver_add("influence")
+            driver = fcurve.driver
+            var = driver.variables.new()
+            driver.type = 'AVERAGE'
+            var.name = "var"
+            var.targets[0].id_type = 'OBJECT'
+            var.targets[0].id = self.obj
+            var.targets[0].data_path = foot_p.path_from_id() + '["ikfk_switch"]'
+
+        con = pb[self.org_bones[1]].constraints.new('COPY_TRANSFORMS')
+        con.name = "ik"
+        con.target = self.obj
+        con.subtarget = shin
+        if self.switch == True:
+            # IK/FK switch driver
+            fcurve = con.driver_add("influence")
+            driver = fcurve.driver
+            var = driver.variables.new()
+            driver.type = 'AVERAGE'
+            var.name = "var"
+            var.targets[0].id_type = 'OBJECT'
+            var.targets[0].id = self.obj
+            var.targets[0].data_path = foot_p.path_from_id() + '["ikfk_switch"]'
+
+        con = pb[self.org_bones[2]].constraints.new('COPY_TRANSFORMS')
+        con.name = "ik"
+        con.target = self.obj
+        con.subtarget = foot_ik_target
+        if self.switch == True:
+            # IK/FK switch driver
+            fcurve = con.driver_add("influence")
+            driver = fcurve.driver
+            var = driver.variables.new()
+            driver.type = 'AVERAGE'
+            var.name = "var"
+            var.targets[0].id_type = 'OBJECT'
+            var.targets[0].id = self.obj
+            var.targets[0].data_path = foot_p.path_from_id() + '["ikfk_switch"]'
+
+        con = pb[self.org_bones[3]].constraints.new('COPY_TRANSFORMS')
+        con.name = "copy_transforms"
+        con.target = self.obj
+        con.subtarget = toe
+
+        # VIS foot constraints
+        con = visfoot_p.constraints.new('COPY_LOCATION')
+        con.name = "copy_loc"
+        con.target = self.obj
+        con.subtarget = self.org_bones[2]
+
+        con = visfoot_p.constraints.new('STRETCH_TO')
+        con.name = "stretch_to"
+        con.target = self.obj
+        con.subtarget = foot
+        con.volume = 'NO_VOLUME'
+        con.rest_length = visfoot_p.length
+
+        # VIS pole constraints
+        con = vispole_p.constraints.new('COPY_LOCATION')
+        con.name = "copy_loc"
+        con.target = self.obj
+        con.subtarget = self.org_bones[1]
+
+        con = vispole_p.constraints.new('STRETCH_TO')
+        con.name = "stretch_to"
+        con.target = self.obj
+        con.subtarget = pole
+        con.volume = 'NO_VOLUME'
+        con.rest_length = vispole_p.length
+
+        # Set layers if specified
+        if self.layers:
+            foot_p.bone.layers = self.layers
+            pole_p.bone.layers = self.layers
+            foot_roll_p.bone.layers = self.layers
+            visfoot_p.bone.layers = self.layers
+            vispole_p.bone.layers = self.layers
+
+            toe_p.bone.layers = [(i[0] or i[1]) for i in zip(toe_p.bone.layers, self.layers)]  # Both FK and IK layers
+
+        # Create widgets
+        create_line_widget(self.obj, vispole)
+        create_line_widget(self.obj, visfoot)
+        create_sphere_widget(self.obj, pole)
+        create_circle_widget(self.obj, toe, radius=0.7, head_tail=0.5)
+
+        ob = create_widget(self.obj, foot)
+        if ob != None:
+            verts = [(0.7, 1.5, 0.0), (0.7, -0.25, 0.0), (-0.7, -0.25, 0.0), (-0.7, 1.5, 0.0), (0.7, 0.723, 0.0), (-0.7, 0.723, 0.0), (0.7, 0.0, 0.0), (-0.7, 0.0, 0.0)]
+            edges = [(1, 2), (0, 3), (0, 4), (3, 5), (4, 6), (1, 6), (5, 7), (2, 7)]
+            mesh = ob.data
+            mesh.from_pydata(verts, edges, [])
+            mesh.update()
+
+            mod = ob.modifiers.new("subsurf", 'SUBSURF')
+            mod.levels = 2
+
+        ob = create_widget(self.obj, foot_roll)
+        if ob != None:
+            verts = [(0.3999999761581421, 0.766044557094574, 0.6427875757217407), (0.17668449878692627, 3.823702598992895e-08, 3.2084670920085046e-08), (-0.17668461799621582, 9.874240447516058e-08, 8.285470443070153e-08), (-0.39999961853027344, 0.7660449147224426, 0.6427879333496094), (0.3562471270561218, 0.6159579753875732, 0.5168500542640686), (-0.35624682903289795, 0.6159582138061523, 0.5168502926826477), (0.20492683351039886, 0.09688037633895874, 0.0812922865152359), (-0.20492687821388245, 0.0968804731965065, 0.08129236847162247)]
+            edges = [(1, 2), (0, 3), (0, 4), (3, 5), (1, 6), (4, 6), (2, 7), (5, 7)]
+            mesh = ob.data
+            mesh.from_pydata(verts, edges, [])
+            mesh.update()
+
+            mod = ob.modifiers.new("subsurf", 'SUBSURF')
+            mod.levels = 2
+
+        return [foot, pole, foot_roll]
+
diff --git a/rigify/rigs/copy.py b/rigify/rigs/copy.py
new file mode 100644
index 0000000000000000000000000000000000000000..61c4cc99799cc8b1492740d9955de9d6b25e750b
--- /dev/null
+++ b/rigify/rigs/copy.py
@@ -0,0 +1,114 @@
+#====================== BEGIN GPL LICENSE BLOCK ======================
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software Foundation,
+#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+#======================= END GPL LICENSE BLOCK ========================
+
+import bpy
+from rigify.utils import MetarigError
+from rigify.utils import copy_bone
+from rigify.utils import strip_org, make_deformer_name
+from rigify.utils import create_bone_widget
+
+
+class Rig:
+    """ A "copy" rig.  All it does is duplicate the original bone and
+        constrain it.
+        This is a control and deformation rig.
+
+    """
+    def __init__(self, obj, bone, params):
+        """ Gather and validate data about the rig.
+        """
+        self.obj = obj
+        self.org_bone = bone
+        self.org_name = strip_org(bone)
+        self.params = params
+
+    def generate(self):
+        """ Generate the rig.
+            Do NOT modify any of the original bones, except for adding constraints.
+            The main armature should be selected and active before this is called.
+
+        """
+        bpy.ops.object.mode_set(mode='EDIT')
+
+        # Make a control bone (copy of original).
+        bone = copy_bone(self.obj, self.org_bone, self.org_name)
+
+        # Make a deformation bone (copy of original, child of original).
+        def_bone = copy_bone(self.obj, self.org_bone, make_deformer_name(self.org_name))
+
+        # Get edit bones
+        eb = self.obj.data.edit_bones
+        bone_e = eb[bone]
+        def_bone_e = eb[def_bone]
+
+        # Parent
+        def_bone_e.use_connect = False
+        def_bone_e.parent = eb[self.org_bone]
+
+        bpy.ops.object.mode_set(mode='OBJECT')
+        pb = self.obj.pose.bones
+
+        # Constrain the original bone.
+        con = pb[self.org_bone].constraints.new('COPY_TRANSFORMS')
+        con.name = "copy_loc"
+        con.target = self.obj
+        con.subtarget = bone
+
+        # Create control widget
+        create_bone_widget(self.obj, bone)
+
+    @classmethod
+    def create_sample(self, obj):
+        """ Create a sample metarig for this rig type.
+
+        """
+        # generated by rigify.utils.write_metarig
+        bpy.ops.object.mode_set(mode='EDIT')
+        arm = obj.data
+
+        bones = {}
+
+        bone = arm.edit_bones.new('Bone')
+        bone.head[:] = 0.0000, 0.0000, 0.0000
+        bone.tail[:] = 0.0000, 0.0000, 0.2000
+        bone.roll = 0.0000
+        bone.use_connect = False
+        bones['Bone'] = bone.name
+
+        bpy.ops.object.mode_set(mode='OBJECT')
+        pbone = obj.pose.bones[bones['Bone']]
+        pbone.rigify_type = 'copy'
+        pbone.lock_location = (False, False, False)
+        pbone.lock_rotation = (False, False, False)
+        pbone.lock_rotation_w = False
+        pbone.lock_scale = (False, False, False)
+        pbone.rotation_mode = 'QUATERNION'
+        pbone.rigify_parameters.add()
+
+        bpy.ops.object.mode_set(mode='EDIT')
+        for bone in arm.edit_bones:
+            bone.select = False
+            bone.select_head = False
+            bone.select_tail = False
+        for b in bones:
+            bone = arm.edit_bones[bones[b]]
+            bone.select = True
+            bone.select_head = True
+            bone.select_tail = True
+            arm.edit_bones.active = bone
+
diff --git a/rigify/rigs/finger.py b/rigify/rigs/finger.py
new file mode 100644
index 0000000000000000000000000000000000000000..de028f3606f82814a5df1ec4c3ce567d2f858492
--- /dev/null
+++ b/rigify/rigs/finger.py
@@ -0,0 +1,409 @@
+#====================== BEGIN GPL LICENSE BLOCK ======================
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software Foundation,
+#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+#======================= END GPL LICENSE BLOCK ========================
+
+import bpy
+from mathutils import Vector
+from rigify.utils import MetarigError
+from rigify.utils import copy_bone
+from rigify.utils import connected_children_names
+from rigify.utils import strip_org, make_mechanism_name, make_deformer_name
+from rigify.utils import get_layers
+from rigify.utils import create_widget, create_line_widget, create_limb_widget
+from rna_prop_ui import rna_idprop_ui_prop_get
+import re
+
+
+class Rig:
+    """ A finger rig.  It takes a single chain of bones.
+        This is a control and deformation rig.
+    """
+    def __init__(self, obj, bone, params):
+        """ Gather and validate data about the rig.
+        """
+        self.obj = obj
+        self.org_bones = [bone] + connected_children_names(obj, bone)
+        self.params = params
+
+        # Get user-specified layers, if they exist
+        if params.separate_extra_layers:
+            self.ex_layers = list(params.extra_layers)
+        else:
+            self.ex_layers = None
+
+        # Get other rig parameters
+        self.primary_rotation_axis = params.primary_rotation_axis
+        self.use_digit_twist = params.use_digit_twist
+
+    def deform(self):
+        """ Generate the deformation rig.
+            Just a copy of the original bones, except the first digit which is a twist bone.
+        """
+        bpy.ops.object.mode_set(mode='EDIT')
+
+        # Create the bones
+        # First bone is a twist bone
+        if self.use_digit_twist:
+            b1a = copy_bone(self.obj, self.org_bones[0], make_deformer_name(strip_org(self.org_bones[0] + ".01")))
+            b1b = copy_bone(self.obj, self.org_bones[0], make_deformer_name(strip_org(self.org_bones[0] + ".02")))
+            b1tip = copy_bone(self.obj, self.org_bones[0], make_mechanism_name(strip_org(self.org_bones[0] + ".tip")))
+        else:
+            b1 = copy_bone(self.obj, self.org_bones[0], make_deformer_name(strip_org(self.org_bones[0])))
+
+        # The rest are normal
+        bones = []
+        for bone in self.org_bones[1:]:
+            bones += [copy_bone(self.obj, bone, make_deformer_name(strip_org(bone)))]
+
+        # Position bones
+        eb = self.obj.data.edit_bones
+        if self.use_digit_twist:
+            b1a_e = eb[b1a]
+            b1b_e = eb[b1b]
+            b1tip_e = eb[b1tip]
+
+            b1tip_e.use_connect = False
+            b1tip_e.tail += Vector((0.1, 0, 0))
+            b1tip_e.head = b1b_e.tail
+            b1tip_e.length = b1a_e.length / 4
+
+            center = (b1a_e.head + b1a_e.tail) / 2
+            b1a_e.tail = center
+            b1b_e.use_connect = False
+            b1b_e.head = center
+
+        # Parenting
+        if self.use_digit_twist:
+            b1b_e.parent = eb[self.org_bones[0]]
+            b1tip_e.parent = eb[self.org_bones[0]]
+        else:
+            eb[b1].use_connect = False
+            eb[b1].parent = eb[self.org_bones[0]]
+
+        for (ba, bb) in zip(bones, self.org_bones[1:]):
+            eb[ba].use_connect = False
+            eb[ba].parent = eb[bb]
+
+        # Constraints
+        if self.use_digit_twist:
+            bpy.ops.object.mode_set(mode='OBJECT')
+            pb = self.obj.pose.bones
+
+            b1a_p = pb[b1a]
+
+            con = b1a_p.constraints.new('COPY_LOCATION')
+            con.name = "copy_location"
+            con.target = self.obj
+            con.subtarget = self.org_bones[0]
+
+            con = b1a_p.constraints.new('COPY_SCALE')
+            con.name = "copy_scale"
+            con.target = self.obj
+            con.subtarget = self.org_bones[0]
+
+            con = b1a_p.constraints.new('DAMPED_TRACK')
+            con.name = "track_to"
+            con.target = self.obj
+            con.subtarget = b1tip
+
+    def control(self):
+        """ Generate the control rig.
+        """
+        bpy.ops.object.mode_set(mode='EDIT')
+
+        # Figure out the name for the control bone (remove the last .##)
+        ctrl_name = re.sub("([0-9]+\.)", "", strip_org(self.org_bones[0])[::-1], count=1)[::-1]
+
+        # Create the bones
+        ctrl = copy_bone(self.obj, self.org_bones[0], ctrl_name)
+
+        helpers = []
+        bones = []
+        for bone in self.org_bones:
+            bones += [copy_bone(self.obj, bone, strip_org(bone))]
+            helpers += [copy_bone(self.obj, bone, make_mechanism_name(strip_org(bone)))]
+
+        # Position bones
+        eb = self.obj.data.edit_bones
+
+        length = 0.0
+        for bone in helpers:
+            length += eb[bone].length
+            eb[bone].length /= 2
+
+        eb[ctrl].length = length * 1.5
+
+        # Parent bones
+        prev = eb[self.org_bones[0]].parent
+        for (b, h) in zip(bones, helpers):
+            b_e = eb[b]
+            h_e = eb[h]
+            b_e.use_connect = False
+            h_e.use_connect = False
+
+            b_e.parent = h_e
+            h_e.parent = prev
+
+            prev = b_e
+
+        # Transform locks and rotation mode
+        bpy.ops.object.mode_set(mode='OBJECT')
+        pb = self.obj.pose.bones
+
+        for bone in bones[1:]:
+            pb[bone].lock_location = True, True, True
+
+        if pb[self.org_bones[0]].bone.use_connect == True:
+            pb[bones[0]].lock_location = True, True, True
+
+        pb[ctrl].lock_scale = True, False, True
+
+        for bone in helpers:
+            pb[bone].rotation_mode = 'XYZ'
+
+        # Drivers
+        i = 1
+        val = 1.2 / (len(self.org_bones) - 1)
+        for bone in helpers:
+            # Add custom prop
+            prop_name = "bend_%02d" % i
+            prop = rna_idprop_ui_prop_get(pb[ctrl], prop_name, create=True)
+            prop["min"] = 0.0
+            prop["max"] = 1.0
+            prop["soft_min"] = 0.0
+            prop["soft_max"] = 1.0
+            if i == 1:
+                pb[ctrl][prop_name] = 0.0
+            else:
+                pb[ctrl][prop_name] = val
+
+            # Add driver
+            if 'X' in self.primary_rotation_axis:
+                fcurve = pb[bone].driver_add("rotation_euler", 0)
+            elif 'Y' in self.primary_rotation_axis:
+                fcurve = pb[bone].driver_add("rotation_euler", 1)
+            else:
+                fcurve = pb[bone].driver_add("rotation_euler", 2)
+
+            driver = fcurve.driver
+            driver.type = 'SCRIPTED'
+
+            var = driver.variables.new()
+            var.name = "ctrl_y"
+            var.targets[0].id_type = 'OBJECT'
+            var.targets[0].id = self.obj
+            var.targets[0].data_path = pb[ctrl].path_from_id() + '.scale[1]'
+
+            var = driver.variables.new()
+            var.name = "bend"
+            var.targets[0].id_type = 'OBJECT'
+            var.targets[0].id = self.obj
+            var.targets[0].data_path = pb[ctrl].path_from_id() + '["' + prop_name + '"]'
+
+            if '-' in self.primary_rotation_axis:
+                driver.expression = "-(1.0-ctrl_y) * bend * 3.14159 * 2"
+            else:
+                driver.expression = "(1.0-ctrl_y) * bend * 3.14159 * 2"
+
+            i += 1
+
+        # Constraints
+        con = pb[helpers[0]].constraints.new('COPY_LOCATION')
+        con.name = "copy_location"
+        con.target = self.obj
+        con.subtarget = ctrl
+
+        con = pb[helpers[0]].constraints.new('COPY_ROTATION')
+        con.name = "copy_rotation"
+        con.target = self.obj
+        con.subtarget = ctrl
+
+        # Constrain org bones to the control bones
+        for (bone, org) in zip(bones, self.org_bones):
+            con = pb[org].constraints.new('COPY_TRANSFORMS')
+            con.name = "copy_transforms"
+            con.target = self.obj
+            con.subtarget = bone
+
+        # Set layers for extra control bones
+        if self.ex_layers:
+            for bone in bones:
+                pb[bone].bone.layers = self.ex_layers
+
+        # Create control widgets
+        w = create_widget(self.obj, ctrl)
+        if w != None:
+            mesh = w.data
+            verts = [(0, 0, 0), (0, 1, 0), (0.05, 1, 0), (0.05, 1.1, 0), (-0.05, 1.1, 0), (-0.05, 1, 0)]
+            if 'Z' in self.primary_rotation_axis:
+                # Flip x/z coordinates
+                temp = []
+                for v in verts:
+                    temp += [(v[2], v[1], v[0])]
+                verts = temp
+            edges = [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 1)]
+            mesh.from_pydata(verts, edges, [])
+            mesh.update()
+
+        for bone in bones:
+            create_limb_widget(self.obj, bone)
+
+    def generate(self):
+        """ Generate the rig.
+            Do NOT modify any of the original bones, except for adding constraints.
+            The main armature should be selected and active before this is called.
+        """
+        self.deform()
+        self.control()
+
+    @classmethod
+    def add_parameters(self, group):
+        """ Add the parameters of this rig type to the
+            RigifyParameters IDPropertyGroup
+        """
+        items = [('X', 'X', ''), ('Y', 'Y', ''), ('Z', 'Z', ''), ('-X', '-X', ''), ('-Y', '-Y', ''), ('-Z', '-Z', '')]
+        group.primary_rotation_axis = bpy.props.EnumProperty(items=items, name="Primary Rotation Axis", default='X')
+
+        group.separate_extra_layers = bpy.props.BoolProperty(name="Separate Secondary Control Layers:", default=False, description="Enable putting the secondary controls on a separate layer from the primary controls.")
+        group.extra_layers = bpy.props.BoolVectorProperty(size=32, description="Layers for the secondary controls to be on.")
+
+        group.use_digit_twist = bpy.props.BoolProperty(name="Digit Twist", default=True, description="Generate the dual-bone twist setup for the first finger digit.")
+
+    @classmethod
+    def parameters_ui(self, layout, obj, bone):
+        """ Create the ui for the rig parameters.
+        """
+        params = obj.pose.bones[bone].rigify_parameters[0]
+
+        r = layout.row()
+        r.prop(params, "separate_extra_layers")
+
+        r = layout.row()
+        r.active = params.separate_extra_layers
+
+        col = r.column(align=True)
+        row = col.row(align=True)
+        row.prop(params, "extra_layers", index=0, toggle=True, text="")
+        row.prop(params, "extra_layers", index=1, toggle=True, text="")
+        row.prop(params, "extra_layers", index=2, toggle=True, text="")
+        row.prop(params, "extra_layers", index=3, toggle=True, text="")
+        row.prop(params, "extra_layers", index=4, toggle=True, text="")
+        row.prop(params, "extra_layers", index=5, toggle=True, text="")
+        row.prop(params, "extra_layers", index=6, toggle=True, text="")
+        row.prop(params, "extra_layers", index=7, toggle=True, text="")
+        row = col.row(align=True)
+        row.prop(params, "extra_layers", index=16, toggle=True, text="")
+        row.prop(params, "extra_layers", index=17, toggle=True, text="")
+        row.prop(params, "extra_layers", index=18, toggle=True, text="")
+        row.prop(params, "extra_layers", index=19, toggle=True, text="")
+        row.prop(params, "extra_layers", index=20, toggle=True, text="")
+        row.prop(params, "extra_layers", index=21, toggle=True, text="")
+        row.prop(params, "extra_layers", index=22, toggle=True, text="")
+        row.prop(params, "extra_layers", index=23, toggle=True, text="")
+
+        col = r.column(align=True)
+        row = col.row(align=True)
+        row.prop(params, "ik_layers", index=8, toggle=True, text="")
+        row.prop(params, "ik_layers", index=9, toggle=True, text="")
+        row.prop(params, "ik_layers", index=10, toggle=True, text="")
+        row.prop(params, "ik_layers", index=11, toggle=True, text="")
+        row.prop(params, "ik_layers", index=12, toggle=True, text="")
+        row.prop(params, "ik_layers", index=13, toggle=True, text="")
+        row.prop(params, "ik_layers", index=14, toggle=True, text="")
+        row.prop(params, "ik_layers", index=15, toggle=True, text="")
+        row = col.row(align=True)
+        row.prop(params, "ik_layers", index=24, toggle=True, text="")
+        row.prop(params, "ik_layers", index=25, toggle=True, text="")
+        row.prop(params, "ik_layers", index=26, toggle=True, text="")
+        row.prop(params, "ik_layers", index=27, toggle=True, text="")
+        row.prop(params, "ik_layers", index=28, toggle=True, text="")
+        row.prop(params, "ik_layers", index=29, toggle=True, text="")
+        row.prop(params, "ik_layers", index=30, toggle=True, text="")
+        row.prop(params, "ik_layers", index=31, toggle=True, text="")
+
+        r = layout.row()
+        r.label(text="Bend rotation axis:")
+        r.prop(params, "primary_rotation_axis", text="")
+
+        col = layout.column()
+        col.prop(params, "use_digit_twist")
+
+    @classmethod
+    def create_sample(self, obj):
+        # generated by rigify.utils.write_metarig
+        bpy.ops.object.mode_set(mode='EDIT')
+        arm = obj.data
+
+        bones = {}
+
+        bone = arm.edit_bones.new('finger.01')
+        bone.head[:] = 0.0000, 0.0000, 0.0000
+        bone.tail[:] = 0.2529, 0.0000, 0.0000
+        bone.roll = 3.1416
+        bone.use_connect = False
+        bones['finger.01'] = bone.name
+        bone = arm.edit_bones.new('finger.02')
+        bone.head[:] = 0.2529, 0.0000, 0.0000
+        bone.tail[:] = 0.4024, 0.0000, -0.0264
+        bone.roll = -2.9671
+        bone.use_connect = True
+        bone.parent = arm.edit_bones[bones['finger.01']]
+        bones['finger.02'] = bone.name
+        bone = arm.edit_bones.new('finger.03')
+        bone.head[:] = 0.4024, 0.0000, -0.0264
+        bone.tail[:] = 0.4975, -0.0000, -0.0610
+        bone.roll = -2.7925
+        bone.use_connect = True
+        bone.parent = arm.edit_bones[bones['finger.02']]
+        bones['finger.03'] = bone.name
+
+        bpy.ops.object.mode_set(mode='OBJECT')
+        pbone = obj.pose.bones[bones['finger.01']]
+        pbone.rigify_type = 'finger'
+        pbone.lock_location = (True, True, True)
+        pbone.lock_rotation = (False, False, False)
+        pbone.lock_rotation_w = False
+        pbone.lock_scale = (False, False, False)
+        pbone.rotation_mode = 'YZX'
+        pbone.rigify_parameters.add()
+        pbone = obj.pose.bones[bones['finger.02']]
+        pbone.rigify_type = ''
+        pbone.lock_location = (False, False, False)
+        pbone.lock_rotation = (False, False, False)
+        pbone.lock_rotation_w = False
+        pbone.lock_scale = (False, False, False)
+        pbone.rotation_mode = 'YZX'
+        pbone = obj.pose.bones[bones['finger.03']]
+        pbone.rigify_type = ''
+        pbone.lock_location = (False, False, False)
+        pbone.lock_rotation = (False, False, False)
+        pbone.lock_rotation_w = False
+        pbone.lock_scale = (False, False, False)
+        pbone.rotation_mode = 'YZX'
+
+        bpy.ops.object.mode_set(mode='EDIT')
+        for bone in arm.edit_bones:
+            bone.select = False
+            bone.select_head = False
+            bone.select_tail = False
+        for b in bones:
+            bone = arm.edit_bones[bones[b]]
+            bone.select = True
+            bone.select_head = True
+            bone.select_tail = True
+            arm.edit_bones.active = bone
+
diff --git a/rigify/rigs/misc/__init__.py b/rigify/rigs/misc/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/rigify/rigs/misc/delta.py b/rigify/rigs/misc/delta.py
new file mode 100644
index 0000000000000000000000000000000000000000..2157970a75af634caff2db0d13a0a7f0936f34d8
--- /dev/null
+++ b/rigify/rigs/misc/delta.py
@@ -0,0 +1,161 @@
+#====================== BEGIN GPL LICENSE BLOCK ======================
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software Foundation,
+#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+#======================= END GPL LICENSE BLOCK ========================
+
+import bpy
+from math import acos
+from rigify.utils import MetarigError
+from rigify.utils import copy_bone
+from rigify.utils import org_name, make_mechanism_name
+
+
+class Rig:
+    """ A delta rig.
+        Creates a setup that will place its child at its position in pose mode,
+        but will not modifying its child's position in edit mode.
+        This is a mechanism-only rig (no control or deformation bones).
+
+    """
+    def __init__(self, obj, bone, params):
+        """ Gather and validate data about the rig.
+            Store any data or references to data that will be needed later on.
+            In particular, store references to bones that will be needed.
+            Do NOT change any data in the scene.  This is a gathering phase only.
+
+        """
+        bb = obj.data.bones
+
+        if bb[bone].children == None:
+            raise MetarigError("RIGIFY ERROR: bone '%s': rig type requires one child." % org_name(bone.name))
+        if bb[bone].use_connect == True:
+            raise MetarigError("RIGIFY ERROR: bone '%s': rig type cannot be connected to parent." % org_name(bone.name))
+
+        self.obj = obj
+        self.org_bones = {"delta": bone, "child": bb[bone].children[0].name}
+        self.org_names = [org_name(bone), org_name(bb[bone].children[0].name)]
+
+    def generate(self):
+        """ Generate the rig.
+            Do NOT modify any of the original bones, except for adding constraints.
+            The main armature should be selected and active before this is called.
+
+        """
+        bpy.ops.object.mode_set(mode='EDIT')
+        eb = self.obj.data.edit_bones
+
+        org_delta = self.org_bones["delta"]
+        org_delta_e = eb[self.org_bones["delta"]]
+        org_child = self.org_bones["child"]
+        org_child_e = eb[self.org_bones["child"]]
+
+        # Calculate the matrix for achieving the delta
+        child_mat = org_delta_e.matrix.invert() * org_child_e.matrix
+        mat = org_delta_e.matrix * child_mat.invert()
+
+        # Create the delta bones.
+        delta_e = eb[copy_bone(self.obj, self.org_bones["delta"])]
+        delta_e.name = make_mechanism_name(self.org_names[0])
+        delta = delta_e.name
+
+        # Set the delta to the matrix's transforms
+        set_mat(self.obj, delta, mat)
+
+        bpy.ops.object.mode_set(mode='OBJECT')
+
+        # Constrain org_delta to delta
+        con = self.obj.pose.bones[org_delta].constraints.new('COPY_TRANSFORMS')
+        con.name = "delta"
+        con.target = self.obj
+        con.subtarget = delta
+
+    @classmethod
+    def create_sample(self, obj):
+        # generated by rigify.utils.write_metarig
+        bpy.ops.object.mode_set(mode='EDIT')
+        arm = obj.data
+
+        bones = {}
+
+        bone = arm.edit_bones.new('delta')
+        bone.head[:] = 0.0000, -0.1198, 0.1253
+        bone.tail[:] = -0.0000, -0.2483, 0.2785
+        bone.roll = -0.0000
+        bone.use_connect = False
+        bones['delta'] = bone.name
+        bone = arm.edit_bones.new('Bone')
+        bone.head[:] = -0.0000, 0.0000, 0.0000
+        bone.tail[:] = -0.0000, 0.0000, 0.2000
+        bone.roll = 0.0000
+        bone.use_connect = False
+        bone.parent = arm.edit_bones[bones['delta']]
+        bones['Bone'] = bone.name
+
+        bpy.ops.object.mode_set(mode='OBJECT')
+        pbone = obj.pose.bones[bones['delta']]
+        pbone.rigify_type = 'misc.delta'
+        pbone.lock_location = (False, False, False)
+        pbone.lock_rotation = (False, False, False)
+        pbone.lock_rotation_w = False
+        pbone.lock_scale = (False, False, False)
+        pbone.rotation_mode = 'QUATERNION'
+        pbone.rigify_parameters.add()
+        pbone = obj.pose.bones[bones['Bone']]
+        pbone.rigify_type = ''
+        pbone.lock_location = (False, False, False)
+        pbone.lock_rotation = (False, False, False)
+        pbone.lock_rotation_w = False
+        pbone.lock_scale = (False, False, False)
+        pbone.rotation_mode = 'QUATERNION'
+
+        bpy.ops.object.mode_set(mode='EDIT')
+        for bone in arm.edit_bones:
+            bone.select = False
+            bone.select_head = False
+            bone.select_tail = False
+        for b in bones:
+            bone = arm.edit_bones[bones[b]]
+            bone.select = True
+            bone.select_head = True
+            bone.select_tail = True
+            arm.edit_bones.active = bone
+
+
+def set_mat(obj, bone_name, matrix):
+    """ Sets the bone to have the given transform matrix.
+    """
+    a = obj.data.edit_bones[bone_name]
+
+    a.head = (0, 0, 0)
+    a.tail = (0, 1, 0)
+
+    a.transform(matrix)
+
+    d = acos(a.matrix.to_quat().dot(matrix.to_quat())) * 2
+
+    roll_1 = a.roll + d
+    roll_2 = a.roll - d
+
+    a.roll = roll_1
+    d1 = a.matrix.to_quat().dot(matrix.to_quat())
+    a.roll = roll_2
+    d2 = a.matrix.to_quat().dot(matrix.to_quat())
+
+    if d1 > d2:
+        a.roll = roll_1
+    else:
+        a.roll = roll_2
+
diff --git a/rigify/rigs/neck_short.py b/rigify/rigs/neck_short.py
new file mode 100644
index 0000000000000000000000000000000000000000..3c34fbda6968c534d4ad4051decfd7fd8bdc7e0e
--- /dev/null
+++ b/rigify/rigs/neck_short.py
@@ -0,0 +1,385 @@
+#====================== BEGIN GPL LICENSE BLOCK ======================
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software Foundation,
+#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+#======================= END GPL LICENSE BLOCK ========================
+
+import bpy
+from mathutils import Vector
+from rigify.utils import MetarigError
+from rigify.utils import copy_bone, flip_bone, put_bone
+from rigify.utils import connected_children_names
+from rigify.utils import strip_org, make_mechanism_name, make_deformer_name
+from rigify.utils import obj_to_bone, create_circle_widget
+from rna_prop_ui import rna_idprop_ui_prop_get
+
+script1 = """
+head_neck = ["%s", "%s"]
+"""
+
+script2 = """
+if is_selected(head_neck[0]):
+    layout.prop(pose_bones[head_neck[0]], '["isolate"]', text="Isolate (" + head_neck[0] + ")", slider=True)
+"""
+
+script3 = """
+if is_selected(head_neck):
+    layout.prop(pose_bones[head_neck[0]], '["neck_follow"]', text="Neck Follow Head (" + head_neck[0] + ")", slider=True)
+"""
+
+
+class Rig:
+    """ A "spine" rig.  It turns a chain of bones into a rig with two controls:
+        One for the hips, and one for the rib cage.
+
+    """
+    def __init__(self, obj, bone_name, params):
+        """ Gather and validate data about the rig.
+
+        """
+        self.obj = obj
+        self.org_bones = [bone_name] + connected_children_names(obj, bone_name)
+        self.params = params
+
+        if len(self.org_bones) <= 1:
+            raise MetarigError("RIGIFY ERROR: Bone '%s': input to rig type must be a chain of 2 or more bones." % (strip_org(bone)))
+
+        self.isolate = False
+        if self.obj.data.bones[bone_name].parent:
+            self.isolate = True
+
+    def gen_deform(self):
+        """ Generate the deformation rig.
+
+        """
+        for name in self.org_bones:
+            bpy.ops.object.mode_set(mode='EDIT')
+            eb = self.obj.data.edit_bones
+
+            # Create deform bone
+            bone_e = eb[copy_bone(self.obj, name)]
+
+            # Change its name
+            bone_e.name = make_deformer_name(strip_org(name))
+            bone_name = bone_e.name
+
+            # Leave edit mode
+            bpy.ops.object.mode_set(mode='OBJECT')
+
+            # Get the pose bone
+            bone = self.obj.pose.bones[bone_name]
+
+            # Constrain to the original bone
+            con = bone.constraints.new('COPY_TRANSFORMS')
+            con.name = "copy_transforms"
+            con.target = self.obj
+            con.subtarget = name
+
+    def gen_control(self):
+        """ Generate the control rig.
+
+        """
+        #---------------------------------
+        # Create the neck and head controls
+        bpy.ops.object.mode_set(mode='EDIT')
+
+        # Create bones
+        neck_ctrl = copy_bone(self.obj, self.org_bones[0], strip_org(self.org_bones[0]))
+        neck_follow = copy_bone(self.obj, self.org_bones[-1], make_mechanism_name(strip_org(self.org_bones[0] + ".follow")))
+
+        head_ctrl = copy_bone(self.obj, self.org_bones[-1], strip_org(self.org_bones[-1]))
+        head_mch = copy_bone(self.obj, self.org_bones[0], make_mechanism_name(strip_org(self.org_bones[-1])))
+        if self.isolate:
+            head_socket1 = copy_bone(self.obj, self.org_bones[-1], make_mechanism_name(strip_org(self.org_bones[-1] + ".socket1")))
+            head_socket2 = copy_bone(self.obj, self.org_bones[-1], make_mechanism_name(strip_org(self.org_bones[-1] + ".socket2")))
+
+        # Create neck chain bones
+        neck = []
+        helpers = []
+        for name in self.org_bones:
+            neck += [copy_bone(self.obj, name, make_mechanism_name(strip_org(name)))]
+            helpers += [copy_bone(self.obj, neck_ctrl, make_mechanism_name(strip_org(name + ".02")))]
+
+        # Fetch edit bones
+        eb = self.obj.data.edit_bones
+
+        neck_ctrl_e = eb[neck_ctrl]
+        neck_follow_e = eb[neck_follow]
+        head_ctrl_e = eb[head_ctrl]
+        head_mch_e = eb[head_mch]
+        if self.isolate:
+            head_socket1_e = eb[head_socket1]
+            head_socket2_e = eb[head_socket2]
+
+        # Parenting
+        head_ctrl_e.use_connect = False
+        head_ctrl_e.parent = neck_ctrl_e.parent
+        head_mch_e.use_connect = False
+        head_mch_e.parent = head_ctrl_e
+
+        if self.isolate:
+            head_socket1_e.use_connect = False
+            head_socket1_e.parent = neck_ctrl_e.parent
+
+            head_socket2_e.use_connect = False
+            head_socket2_e.parent = None
+
+            head_ctrl_e.parent = head_socket2_e
+
+        for (name1, name2) in zip(neck, helpers):
+            eb[name1].use_connect = False
+            eb[name1].parent = eb[name2]
+            eb[name2].use_connect = False
+            eb[name2].parent = neck_ctrl_e.parent
+
+        neck_follow_e.use_connect = False
+        neck_follow_e.parent = neck_ctrl_e.parent
+        neck_ctrl_e.parent = neck_follow_e
+
+        # Position
+        put_bone(self.obj, neck_follow, neck_ctrl_e.head)
+        put_bone(self.obj, head_ctrl, neck_ctrl_e.head)
+        put_bone(self.obj, head_mch, neck_ctrl_e.head)
+        head_mch_e.length /= 2
+
+        if self.isolate:
+            put_bone(self.obj, head_socket1, neck_ctrl_e.head)
+            head_mch_e.length /= 2
+
+            put_bone(self.obj, head_socket2, neck_ctrl_e.head)
+            head_mch_e.length /= 3
+
+        for (name1, name2) in zip(neck, helpers):
+            put_bone(self.obj, name2, eb[name1].head)
+            eb[name2].length /= 3
+
+        # Switch to object mode
+        bpy.ops.object.mode_set(mode='OBJECT')
+        pb = self.obj.pose.bones
+        neck_ctrl_p = pb[neck_ctrl]
+        neck_follow_p = pb[neck_follow]
+        head_ctrl_p = pb[head_ctrl]
+        if self.isolate:
+            head_socket1_p = pb[head_socket1]
+            head_socket2_p = pb[head_socket2]
+
+        # Custom bone appearance
+        neck_ctrl_p.custom_shape_transform = pb[self.org_bones[(len(self.org_bones) - 1) // 2]]
+        head_ctrl_p.custom_shape_transform = pb[self.org_bones[-1]]
+
+        # Custom properties
+        prop = rna_idprop_ui_prop_get(head_ctrl_p, "inf_extent", create=True)
+        head_ctrl_p["inf_extent"] = 0.5
+        prop["min"] = 0.0
+        prop["max"] = 1.0
+        prop["soft_min"] = 0.0
+        prop["soft_max"] = 1.0
+
+        prop = rna_idprop_ui_prop_get(head_ctrl_p, "neck_follow", create=True)
+        head_ctrl_p["neck_follow"] = 1.0
+        prop["min"] = 0.0
+        prop["max"] = 2.0
+        prop["soft_min"] = 0.0
+        prop["soft_max"] = 1.0
+
+        if self.isolate:
+            prop = rna_idprop_ui_prop_get(head_ctrl_p, "isolate", create=True)
+            head_ctrl_p["isolate"] = 0.0
+            prop["min"] = 0.0
+            prop["max"] = 1.0
+            prop["soft_min"] = 0.0
+            prop["soft_max"] = 1.0
+
+        # Constraints
+
+        # Neck follow
+        con = neck_follow_p.constraints.new('COPY_ROTATION')
+        con.name = "copy_rotation"
+        con.target = self.obj
+        con.subtarget = head_ctrl
+
+        fcurve = con.driver_add("influence")
+        driver = fcurve.driver
+        var = driver.variables.new()
+        driver.type = 'SCRIPTED'
+        var.name = "follow"
+        var.targets[0].id_type = 'OBJECT'
+        var.targets[0].id = self.obj
+        var.targets[0].data_path = head_ctrl_p.path_from_id() + '["neck_follow"]'
+        driver.expression = "follow / 2"
+
+        # Isolate
+        if self.isolate:
+            con = head_socket2_p.constraints.new('COPY_LOCATION')
+            con.name = "copy_location"
+            con.target = self.obj
+            con.subtarget = head_socket1
+
+            con = head_socket2_p.constraints.new('COPY_TRANSFORMS')
+            con.name = "copy_transforms"
+            con.target = self.obj
+            con.subtarget = head_socket1
+
+            fcurve = con.driver_add("influence")
+            driver = fcurve.driver
+            var = driver.variables.new()
+            driver.type = 'SCRIPTED'
+            var.name = "isolate"
+            var.targets[0].id_type = 'OBJECT'
+            var.targets[0].id = self.obj
+            var.targets[0].data_path = head_ctrl_p.path_from_id() + '["isolate"]'
+            driver.expression = "1.0 - isolate"
+
+        # Neck chain
+        first = True
+        prev = None
+        i = 0
+        l = len(neck)
+        for (name1, name2, org_name) in zip(neck, helpers, self.org_bones):
+            con = pb[org_name].constraints.new('COPY_TRANSFORMS')
+            con.name = "copy_transforms"
+            con.target = self.obj
+            con.subtarget = name1
+
+            n_con = pb[name2].constraints.new('COPY_TRANSFORMS')
+            n_con.name = "neck"
+            n_con.target = self.obj
+            n_con.subtarget = neck_ctrl
+
+            h_con = pb[name2].constraints.new('COPY_TRANSFORMS')
+            h_con.name = "head"
+            h_con.target = self.obj
+            h_con.subtarget = head_mch
+
+            con = pb[name2].constraints.new('COPY_LOCATION')
+            con.name = "anchor"
+            con.target = self.obj
+            if first:
+                con.subtarget = neck_ctrl
+            else:
+                con.subtarget = prev
+                con.head_tail = 1.0
+
+            # Drivers
+            n = (i + 1) / l
+
+            # Neck influence
+            fcurve = n_con.driver_add("influence")
+            driver = fcurve.driver
+            var = driver.variables.new()
+            driver.type = 'SCRIPTED'
+            var.name = "ext"
+            var.targets[0].id_type = 'OBJECT'
+            var.targets[0].id = self.obj
+            var.targets[0].data_path = head_ctrl_p.path_from_id() + '["inf_extent"]'
+            driver.expression = "1.0 if (%.4f > (1.0-ext) or (1.0-ext) == 0.0) else (%.4f / (1.0-ext))" % (n, n)
+
+            # Head influence
+            if (i + 1) == l:
+                h_con.influence = 1.0
+            else:
+                fcurve = h_con.driver_add("influence")
+                driver = fcurve.driver
+                var = driver.variables.new()
+                driver.type = 'SCRIPTED'
+                var.name = "ext"
+                var.targets[0].id_type = 'OBJECT'
+                var.targets[0].id = self.obj
+                var.targets[0].data_path = head_ctrl_p.path_from_id() + '["inf_extent"]'
+                driver.expression = "0.0 if (%.4f <= (1.0-ext)) else ((%.4f - (1.0-ext)) / ext)" % (n, n)
+
+            first = False
+            prev = name1
+            i += 1
+
+        # Create control widgets
+        w1 = create_circle_widget(self.obj, neck_ctrl, radius=1.0, head_tail=0.5)
+        w2 = create_circle_widget(self.obj, head_ctrl, radius=1.0, head_tail=0.5)
+
+        if w1 != None:
+            obj_to_bone(w1, self.obj, self.org_bones[(len(self.org_bones) - 1) // 2])
+        if w2 != None:
+            obj_to_bone(w2, self.obj, self.org_bones[-1])
+
+        # Return control bones
+        return (head_ctrl, neck_ctrl)
+
+    def generate(self):
+        """ Generate the rig.
+            Do NOT modify any of the original bones, except for adding constraints.
+            The main armature should be selected and active before this is called.
+
+        """
+        self.gen_deform()
+        (head, neck) = self.gen_control()
+
+        script = script1 % (head, neck)
+        if self.isolate:
+            script += script2
+        script += script3
+
+        return [script]
+
+    @classmethod
+    def create_sample(self, obj):
+        # generated by rigify.utils.write_metarig
+        bpy.ops.object.mode_set(mode='EDIT')
+        arm = obj.data
+
+        bones = {}
+
+        bone = arm.edit_bones.new('neck')
+        bone.head[:] = 0.0000, 0.0000, 0.0000
+        bone.tail[:] = 0.0000, -0.0500, 0.1500
+        bone.roll = 0.0000
+        bone.use_connect = False
+        bones['neck'] = bone.name
+        bone = arm.edit_bones.new('head')
+        bone.head[:] = 0.0000, -0.0500, 0.1500
+        bone.tail[:] = 0.0000, -0.0500, 0.4000
+        bone.roll = 3.1416
+        bone.use_connect = True
+        bone.parent = arm.edit_bones[bones['neck']]
+        bones['head'] = bone.name
+
+        bpy.ops.object.mode_set(mode='OBJECT')
+        pbone = obj.pose.bones[bones['neck']]
+        pbone.rigify_type = 'neck_short'
+        pbone.lock_location = (True, True, True)
+        pbone.lock_rotation = (False, False, False)
+        pbone.lock_rotation_w = False
+        pbone.lock_scale = (False, False, False)
+        pbone.rotation_mode = 'QUATERNION'
+        pbone.rigify_parameters.add()
+        pbone = obj.pose.bones[bones['head']]
+        pbone.rigify_type = ''
+        pbone.lock_location = (False, False, False)
+        pbone.lock_rotation = (False, False, False)
+        pbone.lock_rotation_w = False
+        pbone.lock_scale = (False, False, False)
+        pbone.rotation_mode = 'QUATERNION'
+
+        bpy.ops.object.mode_set(mode='EDIT')
+        for bone in arm.edit_bones:
+            bone.select = False
+            bone.select_head = False
+            bone.select_tail = False
+        for b in bones:
+            bone = arm.edit_bones[bones[b]]
+            bone.select = True
+            bone.select_head = True
+            bone.select_tail = True
+            arm.edit_bones.active = bone
+
diff --git a/rigify/rigs/palm.py b/rigify/rigs/palm.py
new file mode 100644
index 0000000000000000000000000000000000000000..5a0fa7737326b363f2c06042e8c1f144417a73f6
--- /dev/null
+++ b/rigify/rigs/palm.py
@@ -0,0 +1,273 @@
+#====================== BEGIN GPL LICENSE BLOCK ======================
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software Foundation,
+#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+#======================= END GPL LICENSE BLOCK ========================
+
+import bpy
+from math import sin, cos, pi
+from rigify.utils import MetarigError
+from rigify.utils import copy_bone
+from rigify.utils import strip_org, deformer, mch
+from rigify.utils import create_widget
+import re
+
+
+def bone_siblings(obj, bone):
+    """ Returns a list of the siblings of the given bone.
+        This requires that the bones has a parent.
+
+    """
+    parent = obj.data.bones[bone].parent
+
+    if parent == None:
+        return []
+
+    bones = []
+
+    for b in parent.children:
+        if b.name != bone:
+            bones += [b.name]
+
+    return bones
+
+
+def bone_distance(obj, bone1, bone2):
+    """ Returns the distance between two bones.
+
+    """
+    vec = obj.data.bones[bone1].head - obj.data.bones[bone2].head
+    return vec.length
+
+
+class Rig:
+    """ A "palm" rig.  A set of sibling bones that bend with each other.
+        This is a control and deformation rig.
+
+    """
+    def __init__(self, obj, bone, params):
+        """ Gather and validate data about the rig.
+        """
+        self.obj = obj
+        self.params = params
+
+        siblings = bone_siblings(obj, bone)
+
+        if len(siblings) == 0:
+            raise MetarigError("RIGIFY ERROR: Bone '%s': must have a parent and at least one sibling." % (strip_org(bone)))
+
+        # Sort list by name and distance
+        siblings.sort()
+        siblings.sort(key=lambda b: bone_distance(obj, bone, b))
+
+        self.org_bones = [bone] + siblings
+
+        # Get rig parameters
+        self.palm_rotation_axis = params.palm_rotation_axis
+
+    def generate(self):
+        """ Generate the rig.
+            Do NOT modify any of the original bones, except for adding constraints.
+            The main armature should be selected and active before this is called.
+
+        """
+        bpy.ops.object.mode_set(mode='EDIT')
+
+        # Figure out the name for the control bone (remove the last .##)
+        last_bone = self.org_bones[-1:][0]
+        ctrl_name = re.sub("([0-9]+\.)", "", strip_org(last_bone)[::-1], count=1)[::-1]
+
+        # Make control bone
+        ctrl = copy_bone(self.obj, last_bone, ctrl_name)
+
+        # Make deformation bones
+        def_bones = []
+        for bone in self.org_bones:
+            b = copy_bone(self.obj, bone, deformer(strip_org(bone)))
+            def_bones += [b]
+
+        # Parenting
+        eb = self.obj.data.edit_bones
+
+        for d, b in zip(def_bones, self.org_bones):
+            eb[d].use_connect = False
+            eb[d].parent = eb[b]
+
+        # Constraints
+        bpy.ops.object.mode_set(mode='OBJECT')
+        pb = self.obj.pose.bones
+
+        i = 0
+        div = len(self.org_bones) - 1
+        for b in self.org_bones:
+            con = pb[b].constraints.new('COPY_TRANSFORMS')
+            con.name = "copy_transforms"
+            con.target = self.obj
+            con.subtarget = ctrl
+            con.target_space = 'LOCAL'
+            con.owner_space = 'LOCAL'
+            con.influence = i / div
+
+            con = pb[b].constraints.new('COPY_ROTATION')
+            con.name = "copy_rotation"
+            con.target = self.obj
+            con.subtarget = ctrl
+            con.target_space = 'LOCAL'
+            con.owner_space = 'LOCAL'
+            if 'X' in self.palm_rotation_axis:
+                con.invert_x = True
+                con.use_x = True
+                con.use_z = False
+            else:
+                con.invert_z = True
+                con.use_x = False
+                con.use_z = True
+            con.use_y = False
+
+            con.influence = (i / div) - (1 - cos((i * pi / 2) / div))
+
+            i += 1
+
+        # Create control widget
+        w = create_widget(self.obj, ctrl)
+        if w != None:
+            mesh = w.data
+            verts = [(0.15780271589756012, 2.086162567138672e-07, -0.30000004172325134), (0.15780259668827057, 1.0, -0.2000001072883606), (-0.15780280530452728, 0.9999999403953552, -0.20000004768371582), (-0.15780259668827057, -2.086162567138672e-07, -0.29999998211860657), (-0.15780256688594818, -2.7089754439657554e-07, 0.30000004172325134), (-0.1578027755022049, 0.9999998807907104, 0.19999995827674866), (0.15780262649059296, 0.9999999403953552, 0.19999989867210388), (0.1578027456998825, 1.4633496903115883e-07, 0.29999998211860657), (0.15780268609523773, 0.2500001788139343, -0.27500003576278687), (-0.15780264139175415, 0.24999985098838806, -0.2749999761581421), (0.15780262649059296, 0.7500000596046448, -0.22500008344650269), (-0.1578027606010437, 0.7499998807907104, -0.2250000238418579), (0.15780265629291534, 0.75, 0.22499991953372955), (0.15780271589756012, 0.2500000596046448, 0.2749999761581421), (-0.15780261158943176, 0.2499997615814209, 0.27500003576278687), (-0.1578027307987213, 0.7499998807907104, 0.22499997913837433)]
+            if 'Z' in self.palm_rotation_axis:
+                # Flip x/z coordinates
+                temp = []
+                for v in verts:
+                    temp += [(v[2], v[1], v[0])]
+                verts = temp
+            edges = [(1, 2), (0, 3), (4, 7), (5, 6), (8, 0), (9, 3), (10, 1), (11, 2), (12, 6), (13, 7), (4, 14), (15, 5), (10, 8), (11, 9), (15, 14), (12, 13)]
+            mesh.from_pydata(verts, edges, [])
+            mesh.update()
+
+            mod = w.modifiers.new("subsurf", 'SUBSURF')
+            mod.levels = 2
+
+    @classmethod
+    def add_parameters(self, group):
+        """ Add the parameters of this rig type to the
+            RigifyParameters IDPropertyGroup
+
+        """
+        items = [('X', 'X', ''), ('Z', 'Z', '')]
+        group.palm_rotation_axis = bpy.props.EnumProperty(items=items, name="Palm Rotation Axis", default='X')
+
+    @classmethod
+    def parameters_ui(self, layout, obj, bone):
+        """ Create the ui for the rig parameters.
+
+        """
+        params = obj.pose.bones[bone].rigify_parameters[0]
+
+        r = layout.row()
+        r.label(text="Primary rotation axis:")
+        r.prop(params, "palm_rotation_axis", text="")
+
+    @classmethod
+    def create_sample(self, obj):
+        # generated by rigify.utils.write_metarig
+        bpy.ops.object.mode_set(mode='EDIT')
+        arm = obj.data
+
+        bones = {}
+
+        bone = arm.edit_bones.new('palm.parent')
+        bone.head[:] = 0.0000, 0.0000, 0.0000
+        bone.tail[:] = 0.0577, 0.0000, -0.0000
+        bone.roll = 3.1416
+        bone.use_connect = False
+        bones['palm.parent'] = bone.name
+        bone = arm.edit_bones.new('palm.04')
+        bone.head[:] = 0.0577, 0.0315, -0.0000
+        bone.tail[:] = 0.1627, 0.0315, -0.0000
+        bone.roll = 3.1416
+        bone.use_connect = False
+        bone.parent = arm.edit_bones[bones['palm.parent']]
+        bones['palm.04'] = bone.name
+        bone = arm.edit_bones.new('palm.03')
+        bone.head[:] = 0.0577, 0.0105, -0.0000
+        bone.tail[:] = 0.1627, 0.0105, -0.0000
+        bone.roll = 3.1416
+        bone.use_connect = False
+        bone.parent = arm.edit_bones[bones['palm.parent']]
+        bones['palm.03'] = bone.name
+        bone = arm.edit_bones.new('palm.02')
+        bone.head[:] = 0.0577, -0.0105, -0.0000
+        bone.tail[:] = 0.1627, -0.0105, -0.0000
+        bone.roll = 3.1416
+        bone.use_connect = False
+        bone.parent = arm.edit_bones[bones['palm.parent']]
+        bones['palm.02'] = bone.name
+        bone = arm.edit_bones.new('palm.01')
+        bone.head[:] = 0.0577, -0.0315, -0.0000
+        bone.tail[:] = 0.1627, -0.0315, -0.0000
+        bone.roll = 3.1416
+        bone.use_connect = False
+        bone.parent = arm.edit_bones[bones['palm.parent']]
+        bones['palm.01'] = bone.name
+
+        bpy.ops.object.mode_set(mode='OBJECT')
+        pbone = obj.pose.bones[bones['palm.parent']]
+        pbone.rigify_type = ''
+        pbone.lock_location = (False, False, False)
+        pbone.lock_rotation = (False, False, False)
+        pbone.lock_rotation_w = False
+        pbone.lock_scale = (False, False, False)
+        pbone.rotation_mode = 'QUATERNION'
+        pbone = obj.pose.bones[bones['palm.04']]
+        pbone.rigify_type = ''
+        pbone.lock_location = (False, False, False)
+        pbone.lock_rotation = (False, True, True)
+        pbone.lock_rotation_w = False
+        pbone.lock_scale = (False, False, False)
+        pbone.rotation_mode = 'YXZ'
+        pbone = obj.pose.bones[bones['palm.03']]
+        pbone.rigify_type = ''
+        pbone.lock_location = (False, False, False)
+        pbone.lock_rotation = (False, True, True)
+        pbone.lock_rotation_w = False
+        pbone.lock_scale = (False, False, False)
+        pbone.rotation_mode = 'YXZ'
+        pbone = obj.pose.bones[bones['palm.02']]
+        pbone.rigify_type = ''
+        pbone.lock_location = (False, False, False)
+        pbone.lock_rotation = (False, True, True)
+        pbone.lock_rotation_w = False
+        pbone.lock_scale = (False, False, False)
+        pbone.rotation_mode = 'YXZ'
+        pbone = obj.pose.bones[bones['palm.01']]
+        pbone.rigify_type = 'palm'
+        pbone.lock_location = (False, False, False)
+        pbone.lock_rotation = (False, True, True)
+        pbone.lock_rotation_w = False
+        pbone.lock_scale = (False, False, False)
+        pbone.rotation_mode = 'YXZ'
+        pbone.rigify_parameters.add()
+
+        bpy.ops.object.mode_set(mode='EDIT')
+        for bone in arm.edit_bones:
+            bone.select = False
+            bone.select_head = False
+            bone.select_tail = False
+        for b in bones:
+            bone = arm.edit_bones[bones[b]]
+            bone.select = True
+            bone.select_head = True
+            bone.select_tail = True
+            arm.edit_bones.active = bone
+
diff --git a/rigify/rigs/spine.py b/rigify/rigs/spine.py
new file mode 100644
index 0000000000000000000000000000000000000000..2318b3b9fa0c0e4232f4063f534d3cf9a19177c1
--- /dev/null
+++ b/rigify/rigs/spine.py
@@ -0,0 +1,484 @@
+#====================== BEGIN GPL LICENSE BLOCK ======================
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software Foundation,
+#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+#======================= END GPL LICENSE BLOCK ========================
+
+import bpy
+from mathutils import Vector
+from rigify.utils import MetarigError
+from rigify.utils import copy_bone, flip_bone, put_bone
+from rigify.utils import connected_children_names
+from rigify.utils import strip_org, make_mechanism_name, make_deformer_name
+from rigify.utils import obj_to_bone, create_circle_widget
+from rna_prop_ui import rna_idprop_ui_prop_get
+
+
+script = """
+hips = "%s"
+ribs = "%s"
+if is_selected([hips, ribs]):
+    layout.prop(pose_bones[ribs], '["pivot_slide"]', text="Pivot Slide (" + ribs + ")", slider=True)
+if is_selected(ribs):
+    layout.prop(pose_bones[ribs], '["isolate"]', text="Isolate Rotation (" + ribs + ")", slider=True)
+"""
+
+
+class Rig:
+    """ A "spine" rig.  It turns a chain of bones into a rig with two controls:
+        One for the hips, and one for the rib cage.
+
+    """
+    def __init__(self, obj, bone_name, params):
+        """ Gather and validate data about the rig.
+
+        """
+        self.obj = obj
+        self.org_bones = [bone_name] + connected_children_names(obj, bone_name)
+        self.params = params
+
+        if len(self.org_bones) <= 1:
+            raise MetarigError("RIGIFY ERROR: Bone '%s': input to rig type must be a chain of 2 or more bones." % (strip_org(bone)))
+
+    def gen_deform(self):
+        """ Generate the deformation rig.
+
+        """
+        for name in self.org_bones:
+            bpy.ops.object.mode_set(mode='EDIT')
+            eb = self.obj.data.edit_bones
+
+            # Create deform bone
+            bone_e = eb[copy_bone(self.obj, name)]
+
+            # Change its name
+            bone_e.name = make_deformer_name(strip_org(name))
+            bone_name = bone_e.name
+
+            # Leave edit mode
+            bpy.ops.object.mode_set(mode='OBJECT')
+
+            # Get the pose bone
+            bone = self.obj.pose.bones[bone_name]
+
+            # Constrain to the original bone
+            con = bone.constraints.new('COPY_TRANSFORMS')
+            con.name = "copy_transforms"
+            con.target = self.obj
+            con.subtarget = name
+
+    def gen_control(self):
+        """ Generate the control rig.
+
+        """
+        #---------------------------------
+        # Create the hip and rib controls
+        bpy.ops.object.mode_set(mode='EDIT')
+
+        # Copy org bones
+        hip_control = copy_bone(self.obj, self.org_bones[0], strip_org(self.org_bones[0]))
+        rib_control = copy_bone(self.obj, self.org_bones[-1], strip_org(self.org_bones[-1]))
+        rib_mch = copy_bone(self.obj, self.org_bones[-1], make_mechanism_name(strip_org(self.org_bones[-1] + ".follow")))
+        hinge = copy_bone(self.obj, self.org_bones[0], make_mechanism_name(strip_org(self.org_bones[-1]) + ".hinge"))
+
+        eb = self.obj.data.edit_bones
+
+        hip_control_e = eb[hip_control]
+        rib_control_e = eb[rib_control]
+        rib_mch_e = eb[rib_mch]
+        hinge_e = eb[hinge]
+
+        # Parenting
+        hip_control_e.use_connect = False
+        rib_control_e.use_connect = False
+        rib_mch_e.use_connect = False
+        hinge_e.use_connect = False
+
+        hinge_e.parent = None
+        rib_control_e.parent = hinge_e
+        rib_mch_e.parent = rib_control_e
+
+        # Position
+        flip_bone(self.obj, hip_control)
+        flip_bone(self.obj, hinge)
+
+        hinge_e.length /= 2
+        rib_mch_e.length /= 2
+
+        put_bone(self.obj, rib_control, hip_control_e.head)
+        put_bone(self.obj, rib_mch, hip_control_e.head)
+
+        bpy.ops.object.mode_set(mode='POSE')
+        bpy.ops.object.mode_set(mode='EDIT')
+        eb = self.obj.data.edit_bones
+
+        # Switch to object mode
+        bpy.ops.object.mode_set(mode='OBJECT')
+        pb = self.obj.pose.bones
+        hip_control_p = pb[hip_control]
+        rib_control_p = pb[rib_control]
+        hinge_p = pb[hinge]
+
+        # No translation on rib control
+        rib_control_p.lock_location = [True, True, True]
+
+        # Hip does not use local location
+        hip_control_p.bone.use_local_location = False
+
+        # Custom hinge property
+        prop = rna_idprop_ui_prop_get(rib_control_p, "isolate", create=True)
+        rib_control_p["isolate"] = 1.0
+        prop["soft_min"] = prop["min"] = 0.0
+        prop["soft_max"] = prop["max"] = 1.0
+
+        # Constraints
+        con = hinge_p.constraints.new('COPY_LOCATION')
+        con.name = "copy_location"
+        con.target = self.obj
+        con.subtarget = hip_control
+
+        con1 = hinge_p.constraints.new('COPY_ROTATION')
+        con1.name = "isolate_off.01"
+        con1.target = self.obj
+        con1.subtarget = hip_control
+
+        con2 = rib_control_p.constraints.new('COPY_SCALE')
+        con2.name = "isolate_off.02"
+        con2.target = self.obj
+        con2.subtarget = hip_control
+        con2.use_offset = True
+        con2.target_space = 'LOCAL'
+        con2.owner_space = 'LOCAL'
+
+        # Drivers for "isolate_off"
+        fcurve = con1.driver_add("influence")
+        driver = fcurve.driver
+        var = driver.variables.new()
+        driver.type = 'AVERAGE'
+        var.name = "var"
+        var.targets[0].id_type = 'OBJECT'
+        var.targets[0].id = self.obj
+        var.targets[0].data_path = rib_control_p.path_from_id() + '["isolate"]'
+        mod = fcurve.modifiers[0]
+        mod.poly_order = 1
+        mod.coefficients[0] = 1.0
+        mod.coefficients[1] = -1.0
+
+        fcurve = con2.driver_add("influence")
+        driver = fcurve.driver
+        var = driver.variables.new()
+        driver.type = 'AVERAGE'
+        var.name = "var"
+        var.targets[0].id_type = 'OBJECT'
+        var.targets[0].id = self.obj
+        var.targets[0].data_path = rib_control_p.path_from_id() + '["isolate"]'
+        mod = fcurve.modifiers[0]
+        mod.poly_order = 1
+        mod.coefficients[0] = 1.0
+        mod.coefficients[1] = -1.0
+
+        # Appearence
+        hip_control_p.custom_shape_transform = pb[self.org_bones[0]]
+        rib_control_p.custom_shape_transform = pb[self.org_bones[-1]]
+
+        #-------------------------
+        # Create flex spine chain
+
+        # Create bones/parenting/positiong
+        bpy.ops.object.mode_set(mode='EDIT')
+        flex_bones = []
+        flex_helpers = []
+        prev_bone = None
+        for b in self.org_bones:
+            # Create bones
+            bone = copy_bone(self.obj, b, make_mechanism_name(strip_org(b) + ".flex"))
+            helper = copy_bone(self.obj, rib_mch, make_mechanism_name(strip_org(b) + ".flex_h"))
+            flex_bones += [bone]
+            flex_helpers += [helper]
+
+            eb = self.obj.data.edit_bones
+            bone_e = eb[bone]
+            helper_e = eb[helper]
+
+            # Parenting
+            bone_e.use_connect = False
+            helper_e.use_connect = False
+            if prev_bone == None:
+                helper_e.parent = eb[hip_control]
+            bone_e.parent = helper_e
+
+            # Position
+            put_bone(self.obj, helper, bone_e.head)
+            helper_e.length /= 4
+
+            prev_bone = bone
+
+        # Constraints
+        bpy.ops.object.mode_set(mode='OBJECT')
+        pb = self.obj.pose.bones
+        rib_control_p = pb[rib_control]
+        rib_mch_p = pb[rib_mch]
+
+        inc = 1.0 / (len(flex_helpers) - 1)
+        inf = 1.0 / (len(flex_helpers) - 1)
+        for b in zip(flex_helpers[1:], flex_bones[:-1], self.org_bones[1:]):
+            bone_p = pb[b[0]]
+
+            # Scale constraints
+            con = bone_p.constraints.new('COPY_SCALE')
+            con.name = "copy_scale1"
+            con.target = self.obj
+            con.subtarget = flex_helpers[0]
+            con.influence = 1.0
+
+            con = bone_p.constraints.new('COPY_SCALE')
+            con.name = "copy_scale2"
+            con.target = self.obj
+            con.subtarget = rib_mch
+            con.influence = inf
+
+            # Bend constraints
+            con = bone_p.constraints.new('COPY_ROTATION')
+            con.name = "bend1"
+            con.target = self.obj
+            con.subtarget = flex_helpers[0]
+            con.influence = 1.0
+
+            con = bone_p.constraints.new('COPY_ROTATION')
+            con.name = "bend2"
+            con.target = self.obj
+            con.subtarget = rib_mch
+            con.influence = inf
+
+            # If not the rib control
+            if b[0] != flex_helpers[-1]:
+                # Custom bend property
+                prop_name = "bend_" + strip_org(b[2])
+                prop = rna_idprop_ui_prop_get(rib_control_p, prop_name, create=True)
+                rib_control_p[prop_name] = inf
+                prop["min"] = 0.0
+                prop["max"] = 1.0
+                prop["soft_min"] = 0.0
+                prop["soft_max"] = 1.0
+
+                # Bend driver
+                fcurve = con.driver_add("influence")
+                driver = fcurve.driver
+                var = driver.variables.new()
+                driver.type = 'AVERAGE'
+                var.name = prop_name
+                var.targets[0].id_type = 'OBJECT'
+                var.targets[0].id = self.obj
+                var.targets[0].data_path = rib_control_p.path_from_id() + '["' + prop_name + '"]'
+
+            # Location constraint
+            con = bone_p.constraints.new('COPY_LOCATION')
+            con.name = "copy_location"
+            con.target = self.obj
+            con.subtarget = b[1]
+            con.head_tail = 1.0
+
+            inf += inc
+
+        #----------------------------
+        # Create reverse spine chain
+
+        # Create bones/parenting/positioning
+        bpy.ops.object.mode_set(mode='EDIT')
+        rev_bones = []
+        prev_bone = None
+        for b in zip(flex_bones, self.org_bones):
+            # Create bones
+            bone = copy_bone(self.obj, b[1], make_mechanism_name(strip_org(b[1]) + ".reverse"))
+            rev_bones += [bone]
+            eb = self.obj.data.edit_bones
+            bone_e = eb[bone]
+
+            # Parenting
+            bone_e.use_connect = False
+            bone_e.parent = eb[b[0]]
+
+            # Position
+            flip_bone(self.obj, bone)
+            bone_e.tail = Vector(eb[b[0]].head)
+            #bone_e.head = Vector(eb[b[0]].tail)
+            if prev_bone == None:
+                pass  # Position base bone wherever you want, for now do nothing (i.e. position at hips)
+            else:
+                put_bone(self.obj, bone, eb[prev_bone].tail)
+
+            prev_bone = bone
+
+        # Constraints
+        bpy.ops.object.mode_set(mode='OBJECT')
+        pb = self.obj.pose.bones
+        prev_bone = None
+        for bone in rev_bones:
+            bone_p = pb[bone]
+
+            con = bone_p.constraints.new('COPY_LOCATION')
+            con.name = "copy_location"
+            con.target = self.obj
+            if prev_bone == None:
+                con.subtarget = hip_control  # Position base bone wherever you want, for now hips
+            else:
+                con.subtarget = prev_bone
+                con.head_tail = 1.0
+            prev_bone = bone
+
+        #---------------------------------------------
+        # Constrain org bones to flex bone's rotation
+        pb = self.obj.pose.bones
+        for b in zip(self.org_bones, flex_bones):
+            con = pb[b[0]].constraints.new('COPY_TRANSFORMS')
+            con.name = "copy_rotation"
+            con.target = self.obj
+            con.subtarget = b[1]
+
+        #---------------------------
+        # Create pivot slide system
+        pb = self.obj.pose.bones
+        bone_p = pb[self.org_bones[0]]
+        rib_control_p = pb[rib_control]
+
+        # Custom pivot_slide property
+        prop = rna_idprop_ui_prop_get(rib_control_p, "pivot_slide", create=True)
+        rib_control_p["pivot_slide"] = 1.0 / len(self.org_bones)
+        prop["min"] = 0.0
+        prop["max"] = 1.0
+        prop["soft_min"] = 1.0 / len(self.org_bones)
+        prop["soft_max"] = 1.0 - (1.0 / len(self.org_bones))
+
+        # Anchor constraint
+        con = bone_p.constraints.new('COPY_LOCATION')
+        con.name = "copy_location"
+        con.target = self.obj
+        con.subtarget = rev_bones[0]
+
+        # Slide constraints
+        i = 1
+        tot = len(rev_bones)
+        for rb in rev_bones:
+            con = bone_p.constraints.new('COPY_LOCATION')
+            con.name = "slide." + str(i)
+            con.target = self.obj
+            con.subtarget = rb
+            con.head_tail = 1.0
+
+            # Driver
+            fcurve = con.driver_add("influence")
+            driver = fcurve.driver
+            var = driver.variables.new()
+            driver.type = 'AVERAGE'
+            var.name = "slide"
+            var.targets[0].id_type = 'OBJECT'
+            var.targets[0].id = self.obj
+            var.targets[0].data_path = rib_control_p.path_from_id() + '["pivot_slide"]'
+            mod = fcurve.modifiers[0]
+            mod.poly_order = 1
+            mod.coefficients[0] = 1 - i
+            mod.coefficients[1] = tot
+
+            i += 1
+
+        # Create control widgets
+        w1 = create_circle_widget(self.obj, hip_control, radius=1.0, head_tail=1.0)
+        w2 = create_circle_widget(self.obj, rib_control, radius=1.0, head_tail=0.0)
+
+        if w1 != None:
+            obj_to_bone(w1, self.obj, self.org_bones[0])
+        if w2 != None:
+            obj_to_bone(w2, self.obj, self.org_bones[-1])
+
+        # Return control names
+        return hip_control, rib_control
+
+    def generate(self):
+        """ Generate the rig.
+            Do NOT modify any of the original bones, except for adding constraints.
+            The main armature should be selected and active before this is called.
+
+        """
+        self.gen_deform()
+        hips, ribs = self.gen_control()
+
+        return [script % (hips, ribs)]
+
+    @classmethod
+    def create_sample(self, obj):
+        # generated by rigify.utils.write_metarig
+        bpy.ops.object.mode_set(mode='EDIT')
+        arm = obj.data
+
+        bones = {}
+
+        bone = arm.edit_bones.new('hips')
+        bone.head[:] = 0.0000, 0.0000, 0.0000
+        bone.tail[:] = -0.0000, -0.0590, 0.2804
+        bone.roll = -0.0000
+        bone.use_connect = False
+        bones['hips'] = bone.name
+        bone = arm.edit_bones.new('spine')
+        bone.head[:] = -0.0000, -0.0590, 0.2804
+        bone.tail[:] = 0.0000, 0.0291, 0.5324
+        bone.roll = 0.0000
+        bone.use_connect = True
+        bone.parent = arm.edit_bones[bones['hips']]
+        bones['spine'] = bone.name
+        bone = arm.edit_bones.new('ribs')
+        bone.head[:] = 0.0000, 0.0291, 0.5324
+        bone.tail[:] = -0.0000, 0.0000, 1.0000
+        bone.roll = -0.0000
+        bone.use_connect = True
+        bone.parent = arm.edit_bones[bones['spine']]
+        bones['ribs'] = bone.name
+
+        bpy.ops.object.mode_set(mode='OBJECT')
+        pbone = obj.pose.bones[bones['hips']]
+        pbone.rigify_type = 'spine'
+        pbone.lock_location = (False, False, False)
+        pbone.lock_rotation = (False, False, False)
+        pbone.lock_rotation_w = False
+        pbone.lock_scale = (False, False, False)
+        pbone.rotation_mode = 'QUATERNION'
+        pbone = obj.pose.bones[bones['spine']]
+        pbone.rigify_type = ''
+        pbone.lock_location = (False, False, False)
+        pbone.lock_rotation = (False, False, False)
+        pbone.lock_rotation_w = False
+        pbone.lock_scale = (False, False, False)
+        pbone.rotation_mode = 'QUATERNION'
+        pbone = obj.pose.bones[bones['ribs']]
+        pbone.rigify_type = ''
+        pbone.lock_location = (False, False, False)
+        pbone.lock_rotation = (False, False, False)
+        pbone.lock_rotation_w = False
+        pbone.lock_scale = (False, False, False)
+        pbone.rotation_mode = 'QUATERNION'
+        pbone = obj.pose.bones[bones['hips']]
+        pbone['rigify_type'] = 'spine'
+
+        bpy.ops.object.mode_set(mode='EDIT')
+        for bone in arm.edit_bones:
+            bone.select = False
+            bone.select_head = False
+            bone.select_tail = False
+        for b in bones:
+            bone = arm.edit_bones[bones[b]]
+            bone.select = True
+            bone.select_head = True
+            bone.select_tail = True
+            arm.edit_bones.active = bone
+
diff --git a/rigify/ui.py b/rigify/ui.py
new file mode 100644
index 0000000000000000000000000000000000000000..a7267c627174f6fced225ec37f57d46cffd6d80f
--- /dev/null
+++ b/rigify/ui.py
@@ -0,0 +1,249 @@
+#====================== BEGIN GPL LICENSE BLOCK ======================
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software Foundation,
+#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+#======================= END GPL LICENSE BLOCK ========================
+
+import bpy
+from bpy.props import *
+from imp import reload
+import rigify
+from rigify.utils import get_rig_type
+from rigify import generate
+from rna_prop_ui import rna_idprop_ui_prop_get
+
+
+class DATA_PT_rigify_buttons(bpy.types.Panel):
+    bl_label = "Rigify Buttons"
+    bl_space_type = 'PROPERTIES'
+    bl_region_type = 'WINDOW'
+    bl_context = "data"
+    #bl_options = {'DEFAULT_OPEN'}
+
+    @classmethod
+    def poll(cls, context):
+        if not context.armature:
+            return False
+        #obj = context.object
+        #if obj:
+        #    return (obj.mode in ('POSE', 'OBJECT', 'EDIT'))
+        #return False
+        return True
+
+    def draw(self, context):
+        C = context
+        layout = self.layout
+        obj = context.object
+
+        if obj.mode in ('POSE', 'OBJECT'):
+            row = layout.row()
+            row.operator("pose.rigify_generate", text="Generate")
+        elif obj.mode == 'EDIT':
+            # Build types list
+            collection_name = str(C.scene.rigify_collection).replace(" ", "")
+
+            for i in range(0, len(C.scene.rigify_types)):
+                C.scene.rigify_types.remove(0)
+
+            for r in rigify.rig_list:
+                collection = r.split('.')[0]
+                if collection_name == "All":
+                    a = C.scene.rigify_types.add()
+                    a.name = r
+                elif r.startswith(collection_name + '.'):
+                    a = C.scene.rigify_types.add()
+                    a.name = r
+                elif collection_name == "None" and len(r.split('.')) == 1:
+                    a = C.scene.rigify_types.add()
+                    a.name = r
+
+            ## Rig collection field
+            #row = layout.row()
+            #row.prop(C.scene, 'rigify_collection', text="Category")
+
+            # Rig type list
+            row = layout.row()
+            row.template_list(C.scene, "rigify_types", C.scene, 'rigify_active_type')
+            row = layout.row()
+            op = row.operator("armature.metarig_sample_add", text="Add sample")
+            op.metarig_type = C.scene.rigify_types[C.scene.rigify_active_type].name
+
+
+class BONE_PT_rigify_buttons(bpy.types.Panel):
+    bl_label = "Rigify Type"
+    bl_space_type = 'PROPERTIES'
+    bl_region_type = 'WINDOW'
+    bl_context = "bone"
+    #bl_options = {'DEFAULT_OPEN'}
+
+    @classmethod
+    def poll(cls, context):
+        if not context.armature or not context.active_pose_bone:
+            return False
+        obj = context.object
+        if obj:
+            return (obj.mode in ('POSE'))
+        return False
+
+    def draw(self, context):
+        C = context
+        bone = context.active_pose_bone
+        collection_name = str(C.scene.rigify_collection).replace(" ", "")
+        rig_name = str(context.active_pose_bone.rigify_type).replace(" ", "")
+
+        layout = self.layout
+
+        # Build types list
+        for i in range(0, len(C.scene.rigify_types)):
+            C.scene.rigify_types.remove(0)
+
+        for r in rigify.rig_list:
+            collection = r.split('.')[0]
+            if collection_name == "All":
+                a = C.scene.rigify_types.add()
+                a.name = r
+            elif r.startswith(collection_name + '.'):
+                a = C.scene.rigify_types.add()
+                a.name = r
+            elif collection_name == "None" and len(r.split('.')) == 1:
+                a = C.scene.rigify_types.add()
+                a.name = r
+
+        # Rig type field
+        row = layout.row()
+        row.prop_search(bone, "rigify_type", C.scene, "rigify_types", text="Rig type:")
+
+        # Rig type parameters / Rig type non-exist alert
+        if rig_name != "":
+            if len(bone.rigify_parameters) < 1:
+                bone.rigify_parameters.add()
+
+            try:
+                rig = get_rig_type(rig_name)
+                rig.Rig
+            except (ImportError, AttributeError):
+                row = layout.row()
+                box = row.box()
+                box.label(text="ALERT: type \"%s\" does not exist!" % rig_name)
+            else:
+                try:
+                    rig.Rig.parameters_ui
+                except AttributeError:
+                    pass
+                else:
+                    col = layout.column()
+                    col.label(text="Options:")
+                    box = layout.box()
+
+                    rig.Rig.parameters_ui(box, C.active_object, bone.name)
+
+
+#class INFO_MT_armature_metarig_add(bpy.types.Menu):
+#    bl_idname = "INFO_MT_armature_metarig_add"
+#    bl_label = "Meta-Rig"
+
+#    def draw(self, context):
+        #import rigify
+
+        #layout = self.layout
+        #layout.operator_context = 'INVOKE_REGION_WIN'
+
+        #for submodule_type in rigify.get_submodule_types():
+        #    text = bpy.path.display_name(submodule_type)
+        #    layout.operator("pose.metarig_sample_add", text=text, icon='OUTLINER_OB_ARMATURE').metarig_type = submodule_type
+
+
+def rigify_report_exception(operator, exception):
+    import traceback
+    import sys
+    import os
+    # find the module name where the error happened
+    # hint, this is the metarig type!
+    exceptionType, exceptionValue, exceptionTraceback = sys.exc_info()
+    fn = traceback.extract_tb(exceptionTraceback)[-1][0]
+    fn = os.path.basename(fn)
+    fn = os.path.splitext(fn)[0]
+    message = []
+    if fn.startswith("__"):
+        message.append("Incorrect armature...")
+    else:
+        message.append("Incorrect armature for type '%s'" % fn)
+    message.append(exception.message)
+
+    message.reverse()  # XXX - stupid! menu's are upside down!
+
+    operator.report(set(['INFO']), '\n'.join(message))
+
+
+class Generate(bpy.types.Operator):
+    '''Generates a rig from the active metarig armature'''
+
+    bl_idname = "pose.rigify_generate"
+    bl_label = "Rigify Generate Rig"
+
+    def execute(self, context):
+        reload(generate)
+
+        try:
+            generate.generate_rig(context, context.object)
+        except rigify.utils.MetarigError as rig_exception:
+            rigify_report_exception(self, rig_exception)
+
+        return {'FINISHED'}
+
+
+class Sample(bpy.types.Operator):
+    '''Create a sample metarig to be modified before generating the final rig.'''
+
+    bl_idname = "armature.metarig_sample_add"
+    bl_label = "Add a sample metarig for a rig type"
+
+    metarig_type = StringProperty(name="Type", description="Name of the rig type to generate a sample of", maxlen=128, default="")
+
+    def execute(self, context):
+        if context.mode == 'EDIT_ARMATURE' and self.metarig_type != "":
+            try:
+                rig = get_rig_type(self.metarig_type).Rig
+                create_sample = rig.create_sample
+            except (ImportError, AttributeError):
+                print("Rigify: rig type has no sample.")
+            else:
+                create_sample(context.active_object)
+            bpy.ops.object.mode_set(mode='EDIT')
+
+        return {'FINISHED'}
+
+
+#menu_func = (lambda self, context: self.layout.menu("INFO_MT_armature_metarig_add", icon='OUTLINER_OB_ARMATURE'))
+
+#import space_info  # ensure the menu is loaded first
+
+def register():
+    #bpy.types.register(DATA_PT_rigify_buttons)
+    #bpy.types.register(BONE_PT_rigify_buttons)
+    #bpy.types.register(Generate)
+    #bpy.types.register(Sample)
+
+    #space_info.INFO_MT_armature_add.append(ui.menu_func)
+    pass
+
+
+def unregister():
+    #bpy.types.unregister(DATA_PT_rigify_buttons)
+    #bpy.types.unregister(BONE_PT_rigify_buttons)
+    #bpy.types.unregister(Generate)
+    #bpy.types.unregister(Sample)
+    pass
+
diff --git a/rigify/utils.py b/rigify/utils.py
new file mode 100644
index 0000000000000000000000000000000000000000..33170ec22c835b9288f9f05dff779091427f457a
--- /dev/null
+++ b/rigify/utils.py
@@ -0,0 +1,497 @@
+#====================== BEGIN GPL LICENSE BLOCK ======================
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software Foundation,
+#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+#======================= END GPL LICENSE BLOCK ========================
+
+import bpy
+from imp import reload
+from random import randint
+from mathutils import Vector
+from math import ceil, floor
+from rna_prop_ui import rna_idprop_ui_prop_get
+
+RIG_DIR = "rigs"  # Name of the directory where rig types are kept
+
+ORG_PREFIX = "ORG-"  # Prefix of original bones.
+MCH_PREFIX = "MCH-"  # Prefix of mechanism bones.
+DEF_PREFIX = "DEF-"  # Prefix of deformation bones.
+WGT_PREFIX = "WGT-"  # Prefix for widget objects
+ROOT_NAME = "root"   # Name of the root bone.
+
+WGT_LAYERS = [x == 19 for x in range(0, 20)]  # Widgets go on the last scene layer.
+
+MODULE_NAME = "rigify"  # Windows/Mac blender is weird, so __package__ doesn't work
+
+
+#=======================================================================
+# Error handling
+#=======================================================================
+class MetarigError(Exception):
+    """ Exception raised for errors.
+    """
+    def __init__(self, message):
+        self.message = message
+
+    def __str__(self):
+        return repr(self.message)
+
+
+#=======================================================================
+# Name manipulation
+#=======================================================================
+def org_name(name):
+    """ Returns the name with ORG_PREFIX stripped from it.
+    """
+    if name.startswith(ORG_PREFIX):
+        return name[len(ORG_PREFIX):]
+    else:
+        return name
+
+
+def strip_org(name):
+    """ Returns the name with ORG_PREFIX stripped from it.
+    """
+    if name.startswith(ORG_PREFIX):
+        return name[len(ORG_PREFIX):]
+    else:
+        return name
+org_name = strip_org
+
+
+def org(name):
+    """ Prepends the ORG_PREFIX to a name if it doesn't already have
+        it, and returns it.
+    """
+    if name.startswith(ORG_PREFIX):
+        return name
+    else:
+        return ORG_PREFIX + name
+make_original_name = org
+
+
+def mch(name):
+    """ Prepends the MCH_PREFIX to a name if it doesn't already have
+        it, and returns it.
+    """
+    if name.startswith(MCH_PREFIX):
+        return name
+    else:
+        return MCH_PREFIX + name
+make_mechanism_name = mch
+
+
+def deformer(name):
+    """ Prepends the DEF_PREFIX to a name if it doesn't already have
+        it, and returns it.
+    """
+    if name.startswith(DEF_PREFIX):
+        return name
+    else:
+        return DEF_PREFIX + name
+make_deformer_name = deformer
+
+
+def insert_before_lr(name, text):
+    if name[-1] in ['l', 'L', 'r', 'R'] and name[-2] in ['.', '-', '_']:
+        return name[:-2] + text + name[-2:]
+    else:
+        return name + text
+
+
+#=======================
+# Bone manipulation
+#=======================
+def new_bone(obj, bone_name):
+    """ Adds a new bone to the given armature object.
+        Returns the resulting bone's name.
+    """
+    if obj == bpy.context.active_object and bpy.context.mode == 'EDIT_ARMATURE':
+        edit_bone = obj.data.edit_bones.new(bone_name)
+        name = edit_bone.name
+        edit_bone.head = (0, 0, 0)
+        edit_bone.tail = (0, 1, 0)
+        edit_bone.roll = 0
+        bpy.ops.object.mode_set(mode='OBJECT')
+        bpy.ops.object.mode_set(mode='EDIT')
+        return name
+    else:
+        raise MetarigError("Can't add new bone '%s' outside of edit mode." % bone_name)
+
+
+def copy_bone(obj, bone_name, assign_name=''):
+    """ Makes a copy of the given bone in the given armature object.
+        Returns the resulting bone's name.
+    """
+    if bone_name not in obj.data.bones:
+        raise MetarigError("copy_bone(): bone '%s' not found, cannot copy it." % bone_name)
+
+    if obj == bpy.context.active_object and bpy.context.mode == 'EDIT_ARMATURE':
+        if assign_name == '':
+            assign_name = bone_name
+        # Copy the edit bone
+        edit_bone_1 = obj.data.edit_bones[bone_name]
+        edit_bone_2 = obj.data.edit_bones.new(assign_name)
+        bone_name_1 = bone_name
+        bone_name_2 = edit_bone_2.name
+
+        edit_bone_2.parent = edit_bone_1.parent
+        edit_bone_2.use_connect = edit_bone_1.use_connect
+
+        # Copy edit bone attributes
+        edit_bone_2.layers = list(edit_bone_1.layers)
+
+        edit_bone_2.head = Vector(edit_bone_1.head)
+        edit_bone_2.tail = Vector(edit_bone_1.tail)
+        edit_bone_2.roll = edit_bone_1.roll
+
+        edit_bone_2.use_inherit_rotation = edit_bone_1.use_inherit_rotation
+        edit_bone_2.use_inherit_scale = edit_bone_1.use_inherit_scale
+        edit_bone_2.use_local_location = edit_bone_1.use_local_location
+
+        edit_bone_2.use_deform = edit_bone_1.use_deform
+        edit_bone_2.bbone_segments = edit_bone_1.bbone_segments
+        edit_bone_2.bbone_in = edit_bone_1.bbone_in
+        edit_bone_2.bbone_out = edit_bone_1.bbone_out
+
+        bpy.ops.object.mode_set(mode='OBJECT')
+
+        # Get the pose bones
+        pose_bone_1 = obj.pose.bones[bone_name_1]
+        pose_bone_2 = obj.pose.bones[bone_name_2]
+
+        # Copy pose bone attributes
+        pose_bone_2.rotation_mode = pose_bone_1.rotation_mode
+        pose_bone_2.rotation_axis_angle = tuple(pose_bone_1.rotation_axis_angle)
+        pose_bone_2.rotation_euler = tuple(pose_bone_1.rotation_euler)
+        pose_bone_2.rotation_quaternion = tuple(pose_bone_1.rotation_quaternion)
+
+        pose_bone_2.lock_location = tuple(pose_bone_1.lock_location)
+        pose_bone_2.lock_scale = tuple(pose_bone_1.lock_scale)
+        pose_bone_2.lock_rotation = tuple(pose_bone_1.lock_rotation)
+        pose_bone_2.lock_rotation_w = pose_bone_1.lock_rotation_w
+        pose_bone_2.lock_rotations_4d = pose_bone_1.lock_rotations_4d
+
+        bpy.ops.object.mode_set(mode='EDIT')
+
+        return bone_name_2
+    else:
+        raise MetarigError("Cannot copy bones outside of edit mode.")
+
+
+def flip_bone(obj, bone_name):
+    """ Flips an edit bone.
+    """
+    if bone_name not in obj.data.bones:
+        raise MetarigError("flip_bone(): bone '%s' not found, cannot copy it." % bone_name)
+
+    if obj == bpy.context.active_object and bpy.context.mode == 'EDIT_ARMATURE':
+        bone = obj.data.edit_bones[bone_name]
+        head = Vector(bone.head)
+        tail = Vector(bone.tail)
+        bone.tail = head + tail
+        bone.head = tail
+        bone.tail = head
+    else:
+        raise MetarigError("Cannot flip bones outside of edit mode.")
+
+
+def put_bone(obj, bone_name, pos):
+    """ Places a bone at the given position.
+    """
+    if bone_name not in obj.data.bones:
+        raise MetarigError("put_bone(): bone '%s' not found, cannot copy it." % bone_name)
+
+    if obj == bpy.context.active_object and bpy.context.mode == 'EDIT_ARMATURE':
+        bone = obj.data.edit_bones[bone_name]
+
+        delta = pos - bone.head
+        bone.translate(delta)
+    else:
+        raise MetarigError("Cannot 'put' bones outside of edit mode.")
+
+
+#=============================================
+# Widget creation
+#=============================================
+
+def obj_to_bone(obj, rig, bone_name):
+    """ Places an object at the location/rotation/scale of the given bone.
+    """
+    if bpy.context.mode == 'EDIT_ARMATURE':
+        raise MetarigError("obj_to_bone(): does not work while in edit mode.")
+
+    bone = rig.data.bones[bone_name]
+
+    mat = rig.matrix_world * bone.matrix_local
+
+    obj.location = mat.translation_part()
+
+    obj.rotation_mode = 'XYZ'
+    obj.rotation_euler = mat.to_euler()
+
+    scl = mat.scale_part()
+    scl_avg = (scl[0] + scl[1] + scl[2]) / 3
+    obj.scale = (bone.length * scl_avg), (bone.length * scl_avg), (bone.length * scl_avg)
+
+
+def create_widget(rig, bone_name):
+    """ Creates an empty widget object for a bone, and returns the object.
+    """
+    obj_name = WGT_PREFIX + bone_name
+    scene = bpy.context.scene
+    # Check if it already exists
+    if obj_name in scene.objects:
+        return None
+    else:
+        mesh = bpy.data.meshes.new(obj_name)
+        obj = bpy.data.objects.new(obj_name, mesh)
+        scene.objects.link(obj)
+
+        obj_to_bone(obj, rig, bone_name)
+        obj.layers = WGT_LAYERS
+
+        return obj
+
+
+# Common Widgets
+
+def create_line_widget(rig, bone_name):
+    """ Creates a basic line widget, a line that spans the length of the bone.
+    """
+    obj = create_widget(rig, bone_name)
+    if obj != None:
+        mesh = obj.data
+        mesh.from_pydata([(0, 0, 0), (0, 1, 0)], [(0, 1)], [])
+        mesh.update()
+
+
+def create_circle_widget(rig, bone_name, radius=1.0, head_tail=0.0):
+    """ Creates a basic circle widget, a circle around the y-axis.
+        radius: the radius of the circle
+        head_tail: where along the length of the bone the circle is (0.0=head, 1.0=tail)
+    """
+    obj = create_widget(rig, bone_name)
+    if obj != None:
+        v = [(0.7071068286895752, 2.980232238769531e-07, -0.7071065306663513), (0.8314696550369263, 2.980232238769531e-07, -0.5555699467658997), (0.9238795042037964, 2.682209014892578e-07, -0.3826831877231598), (0.9807852506637573, 2.5331974029541016e-07, -0.19509011507034302), (1.0, 2.365559055306221e-07, 1.6105803979371558e-07), (0.9807853698730469, 2.2351741790771484e-07, 0.19509044289588928), (0.9238796234130859, 2.086162567138672e-07, 0.38268351554870605), (0.8314696550369263, 1.7881393432617188e-07, 0.5555704236030579), (0.7071068286895752, 1.7881393432617188e-07, 0.7071070075035095), (0.5555702447891235, 1.7881393432617188e-07, 0.8314698934555054), (0.38268327713012695, 1.7881393432617188e-07, 0.923879861831665), (0.19509008526802063, 1.7881393432617188e-07, 0.9807855486869812), (-3.2584136988589307e-07, 1.1920928955078125e-07, 1.000000238418579), (-0.19509072601795197, 1.7881393432617188e-07, 0.9807854294776917), (-0.3826838731765747, 1.7881393432617188e-07, 0.9238795638084412), (-0.5555707216262817, 1.7881393432617188e-07, 0.8314695358276367), (-0.7071071863174438, 1.7881393432617188e-07, 0.7071065902709961), (-0.8314700126647949, 1.7881393432617188e-07, 0.5555698871612549), (-0.923879861831665, 2.086162567138672e-07, 0.3826829195022583), (-0.9807853698730469, 2.2351741790771484e-07, 0.1950896978378296), (-1.0, 2.365559907957504e-07, -7.290432222362142e-07), (-0.9807850122451782, 2.5331974029541016e-07, -0.195091113448143), (-0.9238790273666382, 2.682209014892578e-07, -0.38268423080444336), (-0.831468939781189, 2.980232238769531e-07, -0.5555710196495056), (-0.7071058750152588, 2.980232238769531e-07, -0.707107424736023), (-0.555569052696228, 2.980232238769531e-07, -0.8314701318740845), (-0.38268208503723145, 2.980232238769531e-07, -0.923879861831665), (-0.19508881866931915, 2.980232238769531e-07, -0.9807853102684021), (1.6053570561780361e-06, 2.980232238769531e-07, -0.9999997615814209), (0.19509197771549225, 2.980232238769531e-07, -0.9807847142219543), (0.3826850652694702, 2.980232238769531e-07, -0.9238786101341248), (0.5555717945098877, 2.980232238769531e-07, -0.8314683437347412)]
+        verts = [(a[0] * radius, head_tail, a[2] * radius) for a in v]
+        edges = [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9), (9, 10), (10, 11), (11, 12), (12, 13), (13, 14), (14, 15), (15, 16), (16, 17), (17, 18), (18, 19), (19, 20), (20, 21), (21, 22), (22, 23), (23, 24), (24, 25), (25, 26), (26, 27), (27, 28), (28, 29), (29, 30), (30, 31), (0, 31)]
+        mesh = obj.data
+        mesh.from_pydata(verts, edges, [])
+        mesh.update()
+        return obj
+    else:
+        return None
+
+
+def create_sphere_widget(rig, bone_name):
+    """ Creates a basic sphere widget, three pependicular overlapping circles.
+    """
+    obj = create_widget(rig, bone_name)
+    if obj != None:
+        verts = [(0.3535533845424652, 0.3535533845424652, 0.0), (0.4619397521018982, 0.19134171307086945, 0.0), (0.5, -2.1855694143368964e-08, 0.0), (0.4619397521018982, -0.19134175777435303, 0.0), (0.3535533845424652, -0.3535533845424652, 0.0), (0.19134174287319183, -0.4619397521018982, 0.0), (7.549790126404332e-08, -0.5, 0.0), (-0.1913416087627411, -0.46193981170654297, 0.0), (-0.35355329513549805, -0.35355350375175476, 0.0), (-0.4619397521018982, -0.19134178757667542, 0.0), (-0.5, 5.962440319251527e-09, 0.0), (-0.4619397222995758, 0.1913418024778366, 0.0), (-0.35355326533317566, 0.35355350375175476, 0.0), (-0.19134148955345154, 0.46193987131118774, 0.0), (3.2584136988589307e-07, 0.5, 0.0), (0.1913420855998993, 0.46193960309028625, 0.0), (7.450580596923828e-08, 0.46193960309028625, 0.19134199619293213), (5.9254205098113744e-08, 0.5, 2.323586443253589e-07), (4.470348358154297e-08, 0.46193987131118774, -0.1913415789604187), (2.9802322387695312e-08, 0.35355350375175476, -0.3535533547401428), (2.9802322387695312e-08, 0.19134178757667542, -0.46193981170654297), (5.960464477539063e-08, -1.1151834122813398e-08, -0.5000000596046448), (5.960464477539063e-08, -0.1913418024778366, -0.46193984150886536), (5.960464477539063e-08, -0.35355350375175476, -0.3535533845424652), (7.450580596923828e-08, -0.46193981170654297, -0.19134166836738586), (9.348272556053416e-08, -0.5, 1.624372103492533e-08), (1.043081283569336e-07, -0.4619397521018982, 0.19134168326854706), (1.1920928955078125e-07, -0.3535533845424652, 0.35355329513549805), (1.1920928955078125e-07, -0.19134174287319183, 0.46193966269493103), (1.1920928955078125e-07, -4.7414250303745575e-09, 0.49999991059303284), (1.1920928955078125e-07, 0.19134172797203064, 0.46193966269493103), (8.940696716308594e-08, 0.3535533845424652, 0.35355329513549805), (0.3535534739494324, 0.0, 0.35355329513549805), (0.1913418173789978, -2.9802322387695312e-08, 0.46193966269493103), (8.303572940349113e-08, -5.005858838558197e-08, 0.49999991059303284), (-0.19134165346622467, -5.960464477539063e-08, 0.46193966269493103), (-0.35355329513549805, -8.940696716308594e-08, 0.35355329513549805), (-0.46193963289260864, -5.960464477539063e-08, 0.19134168326854706), (-0.49999991059303284, -5.960464477539063e-08, 1.624372103492533e-08), (-0.4619397521018982, -2.9802322387695312e-08, -0.19134166836738586), (-0.3535534143447876, -2.9802322387695312e-08, -0.3535533845424652), (-0.19134171307086945, 0.0, -0.46193984150886536), (7.662531942287387e-08, 9.546055501630235e-09, -0.5000000596046448), (0.19134187698364258, 5.960464477539063e-08, -0.46193981170654297), (0.3535535931587219, 5.960464477539063e-08, -0.3535533547401428), (0.4619399905204773, 5.960464477539063e-08, -0.1913415789604187), (0.5000000596046448, 5.960464477539063e-08, 2.323586443253589e-07), (0.4619396924972534, 2.9802322387695312e-08, 0.19134199619293213)]
+        edges = [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9), (9, 10), (10, 11), (11, 12), (12, 13), (13, 14), (14, 15), (0, 15), (16, 31), (16, 17), (17, 18), (18, 19), (19, 20), (20, 21), (21, 22), (22, 23), (23, 24), (24, 25), (25, 26), (26, 27), (27, 28), (28, 29), (29, 30), (30, 31), (32, 33), (33, 34), (34, 35), (35, 36), (36, 37), (37, 38), (38, 39), (39, 40), (40, 41), (41, 42), (42, 43), (43, 44), (44, 45), (45, 46), (46, 47), (32, 47)]
+        mesh = obj.data
+        mesh.from_pydata(verts, edges, [])
+        mesh.update()
+
+
+def create_limb_widget(rig, bone_name):
+    """ Creates a basic limb widget, a line that spans the length of the
+        bone, with a circle around the center.
+    """
+    obj = create_widget(rig, bone_name)
+    if obj != None:
+        verts = [(-1.1920928955078125e-07, 1.7881393432617188e-07, 0.0), (3.5762786865234375e-07, 1.0000004768371582, 0.0), (0.1767769455909729, 0.5000001192092896, 0.17677664756774902), (0.20786768198013306, 0.5000001192092896, 0.1388925313949585), (0.23097014427185059, 0.5000001192092896, 0.09567084908485413), (0.24519658088684082, 0.5000001192092896, 0.048772573471069336), (0.2500002384185791, 0.5000001192092896, -2.545945676502015e-09), (0.24519658088684082, 0.5000001192092896, -0.048772573471069336), (0.23097014427185059, 0.5000001192092896, -0.09567084908485413), (0.20786768198013306, 0.5000001192092896, -0.13889259099960327), (0.1767769455909729, 0.5000001192092896, -0.1767767071723938), (0.13889282941818237, 0.5000001192092896, -0.20786744356155396), (0.09567105770111084, 0.5000001192092896, -0.23096990585327148), (0.04877278208732605, 0.5000001192092896, -0.24519634246826172), (1.7279069197684294e-07, 0.5000000596046448, -0.25), (-0.0487724244594574, 0.5000001192092896, -0.24519634246826172), (-0.09567070007324219, 0.5000001192092896, -0.2309698462486267), (-0.13889241218566895, 0.5000001192092896, -0.20786738395690918), (-0.17677652835845947, 0.5000001192092896, -0.17677664756774902), (-0.20786726474761963, 0.5000001192092896, -0.13889244198799133), (-0.23096972703933716, 0.5000001192092896, -0.09567070007324219), (-0.24519610404968262, 0.5000001192092896, -0.04877239465713501), (-0.2499997615814209, 0.5000001192092896, 2.1997936983098043e-07), (-0.24519598484039307, 0.5000001192092896, 0.04877282679080963), (-0.23096948862075806, 0.5000001192092896, 0.09567108750343323), (-0.20786696672439575, 0.5000001192092896, 0.1388927698135376), (-0.1767762303352356, 0.5000001192092896, 0.17677688598632812), (-0.13889199495315552, 0.5000001192092896, 0.2078675627708435), (-0.09567028284072876, 0.5000001192092896, 0.23097002506256104), (-0.048771947622299194, 0.5000001192092896, 0.24519634246826172), (6.555903269145347e-07, 0.5000001192092896, 0.25), (0.04877324402332306, 0.5000001192092896, 0.24519622325897217), (0.09567153453826904, 0.5000001192092896, 0.23096966743469238), (0.13889318704605103, 0.5000001192092896, 0.20786714553833008)]
+        edges = [(0, 1), (2, 3), (4, 3), (5, 4), (5, 6), (6, 7), (8, 7), (8, 9), (10, 9), (10, 11), (11, 12), (13, 12), (14, 13), (14, 15), (16, 15), (16, 17), (17, 18), (19, 18), (19, 20), (21, 20), (21, 22), (22, 23), (24, 23), (25, 24), (25, 26), (27, 26), (27, 28), (29, 28), (29, 30), (30, 31), (32, 31), (32, 33), (2, 33)]
+        mesh = obj.data
+        mesh.from_pydata(verts, edges, [])
+        mesh.update()
+
+
+def create_bone_widget(rig, bone_name):
+    """ Creates a basic bone widget, a simple obolisk-esk shape.
+    """
+    obj = create_widget(rig, bone_name)
+    if obj != None:
+        verts = [(0.04, 1.0, -0.04), (0.1, 0.0, -0.1), (-0.1, 0.0, -0.1), (-0.04, 1.0, -0.04), (0.04, 1.0, 0.04), (0.1, 0.0, 0.1), (-0.1, 0.0, 0.1), (-0.04, 1.0, 0.04)]
+        edges = [(1, 2), (0, 1), (0, 3), (2, 3), (4, 5), (5, 6), (6, 7), (4, 7), (1, 5), (0, 4), (2, 6), (3, 7)]
+        mesh = obj.data
+        mesh.from_pydata(verts, edges, [])
+        mesh.update()
+
+
+def create_root_widget(rig, bone_name):
+    """ Creates a widget for the root bone.
+    """
+    obj = create_widget(rig, bone_name)
+    if obj != None:
+        verts = [(0.7071067690849304, 0.7071067690849304, 0.0), (0.7071067690849304, -0.7071067690849304, 0.0), (-0.7071067690849304, 0.7071067690849304, 0.0), (-0.7071067690849304, -0.7071067690849304, 0.0), (0.8314696550369263, 0.5555701851844788, 0.0), (0.8314696550369263, -0.5555701851844788, 0.0), (-0.8314696550369263, 0.5555701851844788, 0.0), (-0.8314696550369263, -0.5555701851844788, 0.0), (0.9238795042037964, 0.3826834261417389, 0.0), (0.9238795042037964, -0.3826834261417389, 0.0), (-0.9238795042037964, 0.3826834261417389, 0.0), (-0.9238795042037964, -0.3826834261417389, 0.0), (0.9807852506637573, 0.19509035348892212, 0.0), (0.9807852506637573, -0.19509035348892212, 0.0), (-0.9807852506637573, 0.19509035348892212, 0.0), (-0.9807852506637573, -0.19509035348892212, 0.0), (0.19509197771549225, 0.9807849526405334, 0.0), (0.19509197771549225, -0.9807849526405334, 0.0), (-0.19509197771549225, 0.9807849526405334, 0.0), (-0.19509197771549225, -0.9807849526405334, 0.0), (0.3826850652694702, 0.9238788485527039, 0.0), (0.3826850652694702, -0.9238788485527039, 0.0), (-0.3826850652694702, 0.9238788485527039, 0.0), (-0.3826850652694702, -0.9238788485527039, 0.0), (0.5555717945098877, 0.8314685821533203, 0.0), (0.5555717945098877, -0.8314685821533203, 0.0), (-0.5555717945098877, 0.8314685821533203, 0.0), (-0.5555717945098877, -0.8314685821533203, 0.0), (0.19509197771549225, 1.2807848453521729, 0.0), (0.19509197771549225, -1.2807848453521729, 0.0), (-0.19509197771549225, 1.2807848453521729, 0.0), (-0.19509197771549225, -1.2807848453521729, 0.0), (1.280785322189331, 0.19509035348892212, 0.0), (1.280785322189331, -0.19509035348892212, 0.0), (-1.280785322189331, 0.19509035348892212, 0.0), (-1.280785322189331, -0.19509035348892212, 0.0), (0.3950919806957245, 1.2807848453521729, 0.0), (0.3950919806957245, -1.2807848453521729, 0.0), (-0.3950919806957245, 1.2807848453521729, 0.0), (-0.3950919806957245, -1.2807848453521729, 0.0), (1.280785322189331, 0.39509034156799316, 0.0), (1.280785322189331, -0.39509034156799316, 0.0), (-1.280785322189331, 0.39509034156799316, 0.0), (-1.280785322189331, -0.39509034156799316, 0.0), (0.0, 1.5807849168777466, 0.0), (0.0, -1.5807849168777466, 0.0), (1.5807852745056152, 0.0, 0.0), (-1.5807852745056152, 0.0, 0.0)]
+        edges = [(0, 4), (1, 5), (2, 6), (3, 7), (4, 8), (5, 9), (6, 10), (7, 11), (8, 12), (9, 13), (10, 14), (11, 15), (16, 20), (17, 21), (18, 22), (19, 23), (20, 24), (21, 25), (22, 26), (23, 27), (0, 24), (1, 25), (2, 26), (3, 27), (16, 28), (17, 29), (18, 30), (19, 31), (12, 32), (13, 33), (14, 34), (15, 35), (28, 36), (29, 37), (30, 38), (31, 39), (32, 40), (33, 41), (34, 42), (35, 43), (36, 44), (37, 45), (38, 44), (39, 45), (40, 46), (41, 46), (42, 47), (43, 47)]
+        mesh = obj.data
+        mesh.from_pydata(verts, edges, [])
+        mesh.update()
+
+
+#=============================================
+# Misc
+#=============================================
+
+
+def get_rig_type(rig_type):
+    """ Fetches a rig module by name, and returns it.
+    """
+    #print("%s.%s.%s" % (__package__,RIG_DIR,rig_type))
+    submod = __import__(name="%s.%s.%s" % (MODULE_NAME, RIG_DIR, rig_type), fromlist=[rig_type])
+    reload(submod)
+    return submod
+
+
+def connected_children_names(obj, bone_name):
+    """ Returns a list of bone names (in order) of the bones that form a single
+        connected chain starting with the given bone as a parent.
+        If there is a connected branch, the list stops there.
+    """
+    bone = obj.data.bones[bone_name]
+    names = []
+
+    while True:
+        connects = 0
+        con_name = ""
+
+        for child in bone.children:
+            if child.use_connect:
+                connects += 1
+                con_name = child.name
+
+        if connects == 1:
+            names += [con_name]
+            bone = obj.data.bones[con_name]
+        else:
+            break
+
+    return names
+
+
+def get_layers(layers):
+    """ Does it's best to exctract a set of layers from any data thrown at it.
+    """
+    if type(layers) == int:
+        return [x == layers for x in range(0, 32)]
+    elif type(layers) == str:
+        s = layers.split(",")
+        l = []
+        for i in s:
+            try:
+                l += [int(float(i))]
+            except ValueError:
+                pass
+        return [x in l for x in range(0, 32)]
+    elif type(layers) == tuple or type(layers) == list:
+        return [x in layers for x in range(0, 32)]
+    else:
+        try:
+            list(layers)
+        except TypeError:
+            pass
+        else:
+            return [x in layers for x in range(0, 32)]
+
+
+def write_metarig(obj, layers=False, func_name="create_sample"):
+    '''
+    Write a metarig as a python script, this rig is to have all info needed for
+    generating the real rig with rigify.
+    '''
+    code = []
+
+    code.append("def %s(obj):" % func_name)
+    code.append("    # generated by rigify.utils.write_metarig")
+    bpy.ops.object.mode_set(mode='EDIT')
+    code.append("    bpy.ops.object.mode_set(mode='EDIT')")
+    code.append("    arm = obj.data")
+
+    arm = obj.data
+    # write parents first
+    bones = [(len(bone.parent_recursive), bone.name) for bone in arm.edit_bones]
+    bones.sort(key=lambda item: item[0])
+    bones = [item[1] for item in bones]
+
+    code.append("\n    bones = {}\n")
+
+    for bone_name in bones:
+        bone = arm.edit_bones[bone_name]
+        code.append("    bone = arm.edit_bones.new('%s')" % bone.name)
+        code.append("    bone.head[:] = %.4f, %.4f, %.4f" % bone.head.to_tuple(4))
+        code.append("    bone.tail[:] = %.4f, %.4f, %.4f" % bone.tail.to_tuple(4))
+        code.append("    bone.roll = %.4f" % bone.roll)
+        code.append("    bone.use_connect = %s" % str(bone.use_connect))
+        if bone.parent:
+            code.append("    bone.parent = arm.edit_bones[bones['%s']]" % bone.parent.name)
+        code.append("    bones['%s'] = bone.name" % bone.name)
+
+    bpy.ops.object.mode_set(mode='OBJECT')
+    code.append("")
+    code.append("    bpy.ops.object.mode_set(mode='OBJECT')")
+
+    # Rig type and other pose properties
+    for bone_name in bones:
+        pbone = obj.pose.bones[bone_name]
+        pbone_written = False
+
+        code.append("    pbone = obj.pose.bones[bones['%s']]" % bone_name)
+        code.append("    pbone.rigify_type = '%s'" % pbone.rigify_type)
+        code.append("    pbone.lock_location = %s" % str(tuple(pbone.lock_location)))
+        code.append("    pbone.lock_rotation = %s" % str(tuple(pbone.lock_rotation)))
+        code.append("    pbone.lock_rotation_w = %s" % str(pbone.lock_rotation_w))
+        code.append("    pbone.lock_scale = %s" % str(tuple(pbone.lock_scale)))
+        code.append("    pbone.rotation_mode = '%s'" % str(pbone.rotation_mode))
+        if layers:
+            code.append("    pbone.bone.layers = %s" % str(list(pbone.bone.layers)))
+        # Rig type parameters
+        if len(pbone.rigify_parameters) > 0:
+            code.append("    pbone.rigify_parameters.add()")
+            for param_name in pbone.rigify_parameters[0].keys():
+                param = getattr(pbone.rigify_parameters[0], param_name)
+                if str(type(param)) == "<class 'bpy_prop_array'>":
+                    param = list(param)
+                code.append("    try:")
+                code.append("        pbone.rigify_parameters[0].%s = %s" % (param_name, str(param)))
+                code.append("    except AttributeError:")
+                code.append("        pass")
+
+    code.append("\n    bpy.ops.object.mode_set(mode='EDIT')")
+    code.append("    for bone in arm.edit_bones:")
+    code.append("        bone.select = False")
+    code.append("        bone.select_head = False")
+    code.append("        bone.select_tail = False")
+
+    code.append("    for b in bones:")
+    code.append("        bone = arm.edit_bones[bones[b]]")
+    code.append("        bone.select = True")
+    code.append("        bone.select_head = True")
+    code.append("        bone.select_tail = True")
+    code.append("        arm.edit_bones.active = bone")
+
+    return "\n".join(code)
+
+
+def random_string(length):
+    chars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
+    text = ""
+    for i in range(0, length):
+        text += chars[randint(0, 35)]
+    return text
+