# DazV5.5.2 rig, v2 (???)
#
# Updated January 26, 2022
#
# By LordAardvark

import vs
import os

## Flexsort, by LordAardvark
# Helper functions
def GetType( var ):
    return type(var).__name__

def GetChildren( root ):
    children = []
    
    for child in root.children:
        children += [child]
        
        if child.children:
            children += GetChildren(child)
            
    return children
    
# Globals
shot = sfm.GetCurrentShot()
animSet = sfm.GetCurrentAnimationSet()
gameModel = animSet.gameModel
rootGroup = animSet.GetRootControlGroup()

controlGroups = GetChildren(animSet.rootControlGroup)
grpColorRoot = vs.Color(0,128,255,255)
grpColorSub = vs.Color(255,128,32,255)

flexIgnore = ["localViewTargetFactor"] # Flexes to ignore in the renaming and grouping process.

# Custom collectors. Similar to the previous FlexSort system, but a lot less convoluted and still allows flexes outside these groups to be auto-sorted.
grpCollectors = []
grpCollectors.append( [ ["Pussy", "Anus"], "Genitals" ] ) # "[list, of, groups, to, move]" => "group to move them into"
grpCollectors.append( [ ["Nipples"], "Breasts" ] )
grpCollectors.append( [ ["Corset"], "Belly" ] )
grpCollectors.append( [ ["Breasts", "Butt", "Hips", "Thighs", "Belly"], "Bodymorph" ] )
grpCollectors.append( [ ["Cheek", "Nose"], "Middle Face" ] )
grpCollectors.append( [ ["Eyebrow", "Eyelid", "Eyes" ], "Upper Face" ] )
grpCollectors.append( [ ["Jaw", "Lips", "Lip", "Throat" ], "Lower Face" ] )
grpCollectors.append( [ ["Lower Face", "Middle Face", "Upper Face" ], "Face" ] )

grpOrder = [ "Face", "Face.Upper Face", "Face.Upper Face.Eyes", "Face.Upper Face.Eyelid", "Face.Upper Face.Eyelid.Top", "Face.Upper Face.Eyelid.Bottom", "Face.Upper Face.Eyebrow", "Face.Mid Face", "Face.Lower Face", "Bodymorph", "Genitals" ] # Top to bottom reordering of groups.

grpReplace = []
grpReplace.append( [ "Face.Lower Face.Face.Lower Face", "Face.Lower Face" ] ) # No idea why it's doing this, but fuck it. Just brute-force it back.

# Core functions
# https://stackoverflow.com/a/11122355
def GetAllIndices(s, ch):
    return [i for i, ltr in enumerate(s) if ltr == ch]
    
def GetGroupParent( rootGroup, group ):
    parentsToCheck = [ rootGroup ]
    strGroup = str(group)
    
    while len(parentsToCheck) > 0:
        curParent = parentsToCheck[0]
        
        for child in curParent.children:
            if str(child) == strGroup:
                return curParent
                
            parentsToCheck.append(child)
            
        parentsToCheck.remove(curParent)
        
    return None
    
def FindGroup( parent, name ):
    if hasattr(parent,"children"):
        for group in parent.children:
            if str(group.name) == name:
                return group; # The group we are attempting to make already exists. Just return the existing one.
                
    return None
    
def FindGroupFromString (parent, string):
    if parent is None:
        return parent
        
    curParent = parent
    firstGroup = False
    
    groups = string.split('.')
    
    for group in groups:
        curParent = FindGroup( curParent, group )
        
        if not firstGroup:
            firstGroup = curParent
            
    return curParent
            
def CreateGroup( parent, name ):
    if parent.children:
        for group in parent.children:
            if str(group.name) == name:
                return group; # The group we are attempting to make already exists. Just return the existing one.
                
    group = parent.CreateControlGroup( name )
    
    group.SetSelectable ( True )
    
    controlGroups.append( group )
    
    return group
    
def CreateGroupsFromString( parent, string, grpColor ):
    curParent = parent
    firstGroup = False
    
    groups = string.split('.')
    
    for group in groups:
        curParent = CreateGroup( curParent, group )
        
        if not firstGroup:
            firstGroup = curParent
        else:
            curParent.SetGroupColor(grpColor, False)

    parent.RemoveChild(firstGroup)
    parent.children.AddToHead(firstGroup)
    
    return curParent

def AddFlexes():
    flexGrpString = "Flexes."
    
    # Delete the existing Flexes groups, to prevent doubling up flexes
    flexGrp = FindGroup(rootGroup, flexGrpString.replace(".",""))
    if flexGrp is not None:
        rootGroup.RemoveChild(flexGrp)

    flexGrp = CreateGroup(rootGroup, flexGrpString.replace(".",""))

    for ctrl in animSet.controls:
        if GetType(ctrl) is not "CDmElement": # Anything that's not a flex stops the whole loop. This will stop it processing IK constraints.
            break
        else:
            ctrlName = str(ctrl.name)
            
            if ctrlName in flexIgnore:
                continue
                
            # Generate a group-name path from the flex's name, replacing underscores with dots and then properly casing it all.
            flexPathName = str(ctrl.name).replace("_",".")
            dotIndices = GetAllIndices(flexPathName,".")
            
            # Convert string to list, do manipulations, convert back to string. This is dumb.
            flexPathName = list(flexPathName)
            for idx in dotIndices:
                flexPathName[idx+1] = flexPathName[idx+1].upper() # Uppercase the first letter after each dot.
                
            flexPathName[0] = flexPathName[0].upper() # As well as the first name
            
            flexPathName = "".join(flexPathName)
            
            flexPathName = flexGrpString + flexPathName
            
            # Strip the last group out. Don't need it.
            split = flexPathName.split(".")
            split.pop()
            
            flexPathName = ".".join(split)
            
            # Do grouping. Ugly way to do it but bitch I don't care.
            for groupInfo in grpCollectors:
                namesToPrepend = groupInfo[0]
                nameToPrependWith = groupInfo[1]
                
                for strName in namesToPrepend:
                    flexPathName = flexPathName.replace(strName,nameToPrependWith + "." + strName)
                    
            # And replacements
            for replaceInfo in grpReplace:
                nameToReplace = replaceInfo[0]
                nameToReplaceWith = replaceInfo[1]
                
                flexPathName = flexPathName.replace(nameToReplace,nameToReplaceWith)
                
            # Generate the group itself and add the flex to it.
            topGroup = CreateGroupsFromString(rootGroup, flexPathName, grpColorSub)
            
            topGroup.controls.append(ctrl)
       
    flexGrp.SetGroupColor(grpColorRoot, False)
    
    # Do reordering
    for grpName in reversed(grpOrder):
        flexGrp = FindGroupFromString(rootGroup, flexGrpString + grpName)

        if flexGrp is not None:
            parentGrp = GetGroupParent(rootGroup, flexGrp)
            
            parentGrp.RemoveChild(flexGrp)
            parentGrp.children.AddToHead(flexGrp)
            
def RenameFlexes(animset):
    for ctrl in animset.controls:
        if GetType(ctrl) == "CDmElement":
            # Replace dashes with underscores
            ctrlName = str(ctrl.name)
            
            if ctrlName in flexIgnore:
                continue
                
            ctrlName = ctrlName.replace("-","_")
            
            # Change CamelCaseNames to underscore_case_names
            if ctrlName.lower() != ctrlName: # There are upper-case letters. We're going to process these too.
                newName = ctrlName[0] # Gonna just build this character by character, skipping the first character.
                
                for i in range(1,len(ctrlName)):
                    c = ctrlName[i]
                    
                    if c == c.upper(): # Uppercase letter? Add an underscore before the character.
                        newName = newName + "_"
                        
                    newName = newName + c

                ctrlName = newName.lower()
               
            ctrl.name = ctrlName
            
RenameFlexes(animSet)       
AddFlexes()

# BonePresetter loading
DazV5_BonePresetterPath = "LordAardvarkScriptData/BonePresetter/DazV5-5/"

# Helper functions
def VectorCopy(invec):
    outVec = vs.Vector(invec.x, invec.y, invec.z)
    
    return outVec
    
def QuatCopy(inquat):
    outQuat = vs.Quaternion(inquat.x, inquat.y, inquat.z, inquat.w)

    return outQuat
    
def VectorFromString(instr):
    strSplit = instr.split()
    
    if len(strSplit) != 3:
        return None
        
    outVec = vs.Vector(float(strSplit[0]), float(strSplit[1]), float(strSplit[2]))
    
    return outVec
    
def QuaternionFromString(instr):
    strSplit = instr.split()
    
    if len(strSplit) != 4:
        return None
        
    outQuat = vs.Quaternion(float(strSplit[0]), float(strSplit[1]), float(strSplit[2]), float(strSplit[3]))
    
    return outQuat
    
# Make all of the relevant directories in a filepath; Boo not using Python 3.2, means I have to do it this ugly way.
def mkdir_p(path): # http://stackoverflow.com/questions/600268/mkdir-p-functionality-in-python/600612#600612
    try:
        os.makedirs(path)
    except OSError as exc:  # Python >2.5
        if os.path.isdir(path):
            pass
        else:
            raise
            
def GetListItems(list):
    r = []
    
    for i in range(list.count()):
        r.append(list.item(i))
        
    return r
    
def GetControlByName(animset, ctrlName):
    if not hasattr(animset,"controls"):
        return None
        
    for ctrl in animset.controls:
        if str(ctrl.name) == ctrlName:
            return ctrl
            
    return None
    
def GetOrCreatePreset(animset, grpName, presetName):
    if not hasattr(animset,"presetGroups"):
        return None
        
    shot = sfm.GetCurrentShot()
    
    foundPresetGroup = None
    foundPreset = None
    
    for presetGroup in animset.presetGroups:
        if str(presetGroup.name) != grpName:
            continue
            
        foundPresetGroup = presetGroup
        
        for preset in presetGroup.presets:
            if str(preset.name) != presetName:
                continue
                
            foundPreset = preset
            break
       
    # The presetgroup doesn't exist. So we need to create it.     
    if foundPresetGroup is None:
        foundPresetGroup = vs.CreateElement("DmePresetGroup", str(grpName), shot.GetFileId())
        animset.presetGroups.AddToTail(foundPresetGroup)
        
    # The preset doesn't exist. So we need to create it.
    if foundPreset is None:
        foundPreset = vs.CreateElement("DmePreset", str(presetName), shot.GetFileId())
        foundPresetGroup.presets.AddToTail(foundPreset)
        
    return foundPreset
    
# Core logic
def CreatePresetElement(animset, presetData, posOverride=None, rotOverride=None):
    ctrlName, bPos, bRot = presetData
    
    ctrl = GetControlByName(animset, ctrlName)
    
    pos = None
    rot = None
    
    if posOverride is None and hasattr(ctrl,"valuePosition"):
        pos = VectorCopy(ctrl.valuePosition)
        
    if rotOverride is None and hasattr(ctrl,"valueOrientation"):
        rot = QuatCopy(ctrl.valueOrientation)
        
    if posOverride is not None:
        pos = posOverride
        bPos = True
        
    if rotOverride is not None:
        rot = rotOverride
        bRot = True
        
    presetElement = vs.CreateElement("DmeElement",str(ctrlName),shot.GetFileId())
    
    if pos is not None and bPos:
        presetElement.AddAttributeAsVector3("valuePosition")
        presetElement.SetValue("valuePosition",pos)
        
    if rot is not None and bRot:
        presetElement.AddAttributeAsQuaternion("valueOrientation")
        presetElement.SetValue("valueOrientation",rot)
        
    return presetElement
            
def LoadPresetData(animset, fName):
    with open(fName,"r") as f:
        grpName = f.readline().strip()
        presetName = f.readline().strip()
        
        numCtrlValues = int(f.readline().strip())
        
        preset = GetOrCreatePreset(animset, grpName, presetName)
        
        for i in range(numCtrlValues):
            ctrlName = f.readline().strip()
            strPos = f.readline().strip()
            strRot = f.readline().strip()
            
            pos = VectorFromString(strPos)
            rot = QuaternionFromString(strRot)
            
            presetElement = CreatePresetElement(animset, [ctrlName, False, False], posOverride=pos, rotOverride=rot)
            
            preset.controlValues.AddToTail(presetElement)
            
def LoadPresetFolder(animset, fPath):
    mkdir_p(fPath)
    
    for fName in os.listdir(fPath):
        fullPath = os.path.join(fPath, fName)
        
        LoadPresetData(animset, fullPath)
        
LoadPresetFolder(sfm.GetCurrentAnimationSet(), DazV5_BonePresetterPath)

## End BonePresetter

def ControlsByPartialNames( animset, lstNames ):
    rList = []
    
    for ctrl in animset.controls:
        cname = str(ctrl.name).lower()
        if not GetType(ctrl) is "CDmeTransformControl":
            continue
            
        for partialName in lstNames:
            pname = partialName.lower()
            
            if pname in cname:
                rList.append(ctrl)
                break
                
    return rList
            
#==================================================================================================
def AddValidObjectToList( objectList, obj ):
    if ( obj != None ): objectList.append( obj )
    

#==================================================================================================
def HideControlGroups( rig, rootGroup, *groupNames ):
    for name in groupNames:    
        group = rootGroup.FindChildByName( name, False )
        if ( group != None ):
            rig.HideControlGroup( group )

    
#==================================================================================================
# Create the reverse foot control and operators for the foot on the specified side
#==================================================================================================
def CreateReverseFoot( controlName, sideName, gameModel, animSet, shot, helperControlGroup, footControlGroup ) :
    
    # Cannot create foot controls without heel position, so check for that first
    heelAttachName = "pvt_heel_" + sideName
    if ( gameModel.FindAttachment( heelAttachName ) == 0 ):
        print "Could not create foot control " + controlName + ", model is missing heel attachment point: " + heelAttachName;
        return None
    
    footRollDefault = 0.5
    rotationAxis = vs.Vector( 1, 0, 0 )
        
    # Construct the name of the dag nodes of the foot and toe for the specified side
    footName = "rig_foot_" + sideName
    toeName = "rig_toe_" + sideName    
    
    # Get the world space position and orientation of the foot and toe
    footPos = sfm.GetPosition( footName )
    footRot = sfm.GetRotation( footName )
    toePos = sfm.GetPosition( toeName )
    
    # Setup the reverse foot hierarchy such that the foot is the parent of all the foot transforms, the 
    # reverse heel is the parent of the heel, so it can be used for rotations around the ball of the 
    # foot that will move the heel, the heel is the parent of the foot IK handle so that it can perform
    # rotations around the heel and move the foot IK handle, resulting in moving all the foot bones.
    # root
    #   + rig_foot_R
    #       + rig_knee_R
    #       + rig_reverseHeel_R
    #           + rig_heel_R
    #               + rig_footIK_R
    
  
    # Construct the reverse heel joint this will be used to rotate the heel around the toe, and as
    # such is positioned at the toe, but using the rotation of the foot which will be its parent, 
    # so that it has no local rotation once parented to the foot.
    reverseHeelName = "rig_reverseHeel_" + sideName
    reverseHeelDag = sfm.CreateRigHandle( reverseHeelName, pos=toePos, rot=footRot, rotControl=False )
    sfmUtils.Parent( reverseHeelName, footName, vs.REPARENT_LOGS_OVERWRITE )
    
    
    
    # Construct the heel joint, this will be used to rotate the foot around the back of the heel so it 
    # is created at the heel location (offset from the foot) and also given the rotation of its parent.
    heelName = "rig_heel_" + sideName
    vecHeelPos = gameModel.ComputeAttachmentPosition( heelAttachName )
    heelPos = [ vecHeelPos.x, vecHeelPos.y, vecHeelPos.z ]     
    heelRot = sfm.GetRotation( reverseHeelName )
    heelDag = sfm.CreateRigHandle( heelName, pos=heelPos, rot=heelRot, posControl=True, rotControl=False )
    sfmUtils.Parent( heelName, reverseHeelName, vs.REPARENT_LOGS_OVERWRITE )
    
    # Create the ik handle which will be used as the target for the ik chain for the leg
    ikHandleName = "rig_footIK_" + sideName   
    ikHandleDag = sfmUtils.CreateHandleAt( ikHandleName, footName )
    sfmUtils.Parent( ikHandleName, heelName, vs.REPARENT_LOGS_OVERWRITE )
                    
    # Create an orient constraint which causes the toe's orientation to match the foot's orientation
    footRollControlName = controlName + "_" + sideName
    toeOrientTarget = sfm.OrientConstraint( footName, toeName, mo=True, controls=False )
    footRollControl, footRollValue = sfmUtils.CreateControlledValue( footRollControlName, "value", vs.AT_FLOAT, footRollDefault, animSet, shot )
    
    # Create the expressions to re-map the footroll slider value for use in the constraint and rotation operators
    toeOrientExprName = "expr_toeOrientEnable_" + sideName    
    toeOrientExpr = sfmUtils.CreateExpression( toeOrientExprName, "inrange( footRoll, 0.5001, 1.0 )", animSet )
    toeOrientExpr.SetValue( "footRoll", footRollDefault )
    
    toeRotateExprName = "expr_toeRotation_" + sideName
    toeRotateExpr = sfmUtils.CreateExpression( toeRotateExprName, "max( 0, (footRoll - 0.5) ) * 140", animSet )
    toeRotateExpr.SetValue( "footRoll", footRollDefault )
                            
    heelRotateExprName = "expr_heelRotation_" + sideName
    heelRotateExpr = sfmUtils.CreateExpression( heelRotateExprName, "max( 0, (0.5 - footRoll) ) * -100", animSet )
    heelRotateExpr.SetValue( "footRoll", footRollDefault )
        
    # Create a connection from the footroll value to all of the expressions that require it
    footRollConnName = "conn_footRoll_" + sideName
    footRollConn = sfmUtils.CreateConnection( footRollConnName, footRollValue, "value", animSet )
    footRollConn.AddOutput( toeOrientExpr, "footRoll" )
    footRollConn.AddOutput( toeRotateExpr, "footRoll" )
    footRollConn.AddOutput( heelRotateExpr, "footRoll" )
    
    # Create the connection from the toe orientation enable expression to the target weight of the 
    # toe orientation constraint, this will turn the constraint on an off based on the footRoll value
    toeOrientConnName = "conn_toeOrientExpr_" + sideName;
    toeOrientConn = sfmUtils.CreateConnection( toeOrientConnName, toeOrientExpr, "result", animSet )
    toeOrientConn.AddOutput( toeOrientTarget, "targetWeight" )
    
    # Create a rotation constraint to drive the toe rotation and connect its input to the 
    # toe rotation expression and connect its output to the reverse heel dag's orientation
    toeRotateConstraintName = "rotationConstraint_toe_" + sideName
    toeRotateConstraint = sfmUtils.CreateRotationConstraint( toeRotateConstraintName, rotationAxis, reverseHeelDag, animSet )
    
    toeRotateExprConnName = "conn_toeRotateExpr_" + sideName
    toeRotateExprConn = sfmUtils.CreateConnection( toeRotateExprConnName, toeRotateExpr, "result", animSet )
    toeRotateExprConn.AddOutput( toeRotateConstraint, "rotations", 0 );

    # Create a rotation constraint to drive the heel rotation and connect its input to the 
    # heel rotation expression and connect its output to the heel dag's orientation 
    heelRotateConstraintName = "rotationConstraint_heel_" + sideName
    heelRotateConstraint = sfmUtils.CreateRotationConstraint( heelRotateConstraintName, rotationAxis, heelDag, animSet )
    
    heelRotateExprConnName = "conn_heelRotateExpr_" + sideName
    heelRotateExprConn = sfmUtils.CreateConnection( heelRotateExprConnName, heelRotateExpr, "result", animSet )
    heelRotateExprConn.AddOutput( heelRotateConstraint, "rotations", 0 )
    
    if ( helperControlGroup != None ):
        sfmUtils.AddDagControlsToGroup( helperControlGroup, reverseHeelDag, ikHandleDag, heelDag )       
    
    if ( footControlGroup != None ):
        footControlGroup.AddControl( footRollControl )
        
    return ikHandleDag


#==================================================================================================
# Compute the direction from boneA to boneB
#==================================================================================================
def ComputeVectorBetweenBones( boneA, boneB, scaleFactor ):
    
    vPosA = vs.Vector( 0, 0, 0 )
    boneA.GetAbsPosition( vPosA )
    
    vPosB = vs.Vector( 0, 0, 0 )
    boneB.GetAbsPosition( vPosB )
    
    vDir = vs.Vector( 0, 0, 0 )
    vs.mathlib.VectorSubtract( vPosB, vPosA, vDir )
    vDir.NormalizeInPlace()
    
    vScaledDir = vs.Vector( 0, 0, 0 )
    vs.mathlib.VectorScale( vDir, scaleFactor, vScaledDir )    
    
    return vScaledDir
    
   
#==================================================================================================
# Build a simple ik rig for the currently selected animation set
#==================================================================================================
def BuildRig():
    
    # Get the currently selected animation set and shot
    shot = sfm.GetCurrentShot()
    animSet = sfm.GetCurrentAnimationSet()
    gameModel = animSet.gameModel
    rootGroup = animSet.GetRootControlGroup()
    
    # Start the biped rig to which all of the controls and constraints will be added
    rig = sfm.BeginRig( "rig_biped_" + animSet.GetName() );
    if ( rig == None ):
        return
    
    # Change the operation mode to passthrough so changes chan be made temporarily
    sfm.SetOperationMode( "Pass" )
    
    # Move everything into the reference pose
    sfm.SelectAll()
    sfm.SetReferencePose()
    
    #==============================================================================================
    # Find the dag nodes for all of the bones in the model which will be used by the script
    #==============================================================================================    
    boneRoot      = sfmUtils.FindFirstDag( [ "RootTransform" ], True )
    bonePelvis    = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_Pelvis",		"Bip01_Pelvis",		"bip_pelvis" ], True )
    boneSpine0    = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_Spine",		"Bip01_Spine",		"bip_spine_0" ], True )
    boneSpine1    = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_Spine1",		"Bip01_Spine1",		"bip_spine_1" ], True )
    boneSpine2    = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_Spine2",		"Bip01_Spine2",		"bip_spine_2" ], True ) 
    boneSpine3    = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_Spine4",		"Bip01_Spine3",		"bip_spine_2" ], True ) 
    boneNeck1      = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_Neck",		"Neck",		"bip_neck_0",	"bip_neck", "ValveBiped.Bip01_Neck1" ], True )
    boneHead      = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_Head1",		"Head",		"bip_head",		"ValveBiped.Bip01_Head1" ], True )
    
    boneUpperLegR = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Thigh",    "Bip01_R_Thigh",    "bip_hip_R" ], True )
    boneLowerLegR = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Calf",     "Bip01_R_Calf",     "bip_knee_R" ], True )
    boneFootR     = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Foot",     "Bip01_R_Foot",     "bip_foot_R" ], True )
    boneToeR      = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Toe0",     "Bip01_R_Toe0",     "bip_toe_R" ], True ) 
    boneCollarR   = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Clavicle", "Bip01_R_Clavicle", "bip_collar_R" ], True )   
    boneUpperArmR = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Upperarm", "Bip01_R_UpperArm", "bip_upperArm_R" ], True ) 
    boneLowerArmR = sfmUtils.FindFirstDag( [ "ValveBIped.Bip01_R_Forearm",  "Bip01_R_Forearm",  "bip_lowerArm_R" ], True )
    boneHandR     = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Hand",     "Bip01_R_Hand",     "bip_hand_R" ], True )
   
    boneUpperLegL = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Thigh",    "Bip01_L_Thigh",    "bip_hip_L" ], True )
    boneLowerLegL = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Calf",     "Bip01_L_Calf",     "bip_knee_L" ], True )
    boneFootL     = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Foot",     "Bip01_L_Foot",     "bip_foot_L" ], True )
    boneToeL      = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Toe0",     "Bip01_L_Toe0",     "bip_toe_L" ], True ) 
    boneCollarL   = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Clavicle", "Bip01_L_Clavicle", "bip_collar_L" ], True )   
    boneUpperArmL = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Upperarm", "Bip01_L_UpperArm", "bip_upperArm_L" ], True ) 
    boneLowerArmL = sfmUtils.FindFirstDag( [ "ValveBIped.Bip01_L_Forearm",  "Bip01_L_Forearm",  "bip_lowerArm_L" ], True )
    boneHandL     = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Hand",     "Bip01_L_Hand",     "bip_hand_L" ], True )
    
    boneUpperLegTwist1L = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Thigh_Rig" ], True )
    boneLowerLegTwistL = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Calf_Rig" ], True )
    boneFootTwistL = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Foot_Rig" ], True )
    boneUpperLegTwist1R = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Thigh_Rig" ], True )
    boneLowerLegTwistR = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Calf_Rig" ], True )
    boneFootTwistR = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Foot_Rig" ], True )
    
    boneCollarTwistL = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Clavicle_Rig" ], True )
    boneUpperArmTwist1L = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_UpperArm_Rig" ], True )
    boneUpperArmTwist2L = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_UpperArm_Twist" ], True )
    boneLowerArmTwist1L = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Forearm_Rig" ], True )
    boneLowerArmTwist2L = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Forearm_Twist" ], True )
    boneCollarTwistR = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Clavicle_Rig" ], True )
    boneUpperArmTwist1R = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_UpperArm_Rig" ], True )
    boneUpperArmTwist2R = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_UpperArm_Twist" ], True )
    boneLowerArmTwist1R = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Forearm_Rig" ], True )
    boneLowerArmTwist2R = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Forearm_Twist" ], True )
    
    boneFinger00r = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Finger0" ], True )
    boneFinger01r = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Finger01" ], True )
    boneFinger02r = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Finger02" ], True )
    boneFinger10r = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Finger1" ], True )
    boneFinger11r = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Finger11" ], True )
    boneFinger12r = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Finger12" ], True )
    boneFinger20r = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Finger2" ], True )
    boneFinger21r = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Finger21" ], True )
    boneFinger22r = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Finger22" ], True )
    boneFinger30r = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Finger3" ], True )
    boneFinger31r = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Finger31" ], True )
    boneFinger32r = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Finger32" ], True )
    boneFinger40r = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Finger4" ], True )
    boneFinger41r = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Finger41" ], True )
    boneFinger42r = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Finger42" ], True )
    
    boneFinger00l = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Finger0" ], True )
    boneFinger01l = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Finger01" ], True )
    boneFinger02l = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Finger02" ], True )
    boneFinger10l = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Finger1" ], True )
    boneFinger11l = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Finger11" ], True )
    boneFinger12l = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Finger12" ], True )
    boneFinger20l = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Finger2" ], True )
    boneFinger21l = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Finger21" ], True )
    boneFinger22l = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Finger22" ], True )
    boneFinger30l = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Finger3" ], True )
    boneFinger31l = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Finger31" ], True )
    boneFinger32l = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Finger32" ], True )
    boneFinger40l = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Finger4" ], True )
    boneFinger41l = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Finger41" ], True )
    boneFinger42l = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Finger42" ], True )
	
    boneToe00r = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Toe00" ], True )
    boneToe01r = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Toe01" ], True )
    boneToe10r = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Toe10" ], True )
    boneToe11r = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Toe11" ], True )
    boneToe20r = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Toe20" ], True )
    boneToe21r = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Toe21" ], True )
    boneToe30r = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Toe30" ], True )
    boneToe31r = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Toe31" ], True )
    boneToe40r = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Toe40" ], True )
    boneToe41r = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Toe41" ], True )
	
    boneToe00l = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Toe00" ], True )
    boneToe01l = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Toe01" ], True )
    boneToe10l = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Toe10" ], True )
    boneToe11l = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Toe11" ], True )
    boneToe20l = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Toe20" ], True )
    boneToe21l = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Toe21" ], True )
    boneToe30l = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Toe30" ], True )
    boneToe31l = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Toe31" ], True )
    boneToe40l = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Toe40" ], True )
    boneToe41l = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Toe41" ], True )
    
    boneBreastRootR = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Breast0_jiggle_root" ], True )
    boneBreast0R = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Breast0" ], True )
    boneBreast1R = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Breast1" ], True )
    boneBreast2R = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Breast2" ], True )
    boneButt0R = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Butt0" ], True )
    boneButt1R = sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_R_Butt1" ], True )

    boneBreastRootL =  sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Breast0_jiggle_root" ], True )
    boneBreast0L =  sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Breast0" ], True )
    boneBreast1L =  sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Breast1" ], True )
    boneBreast2L =  sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Breast2" ], True )
    boneButt0L =  sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Butt0" ], True )
    boneButt1L =  sfmUtils.FindFirstDag( [ "ValveBiped.Bip01_L_Butt1" ], True )

    rawBonesGenitals = ControlsByPartialNames( animSet, [ "genital" ] )
    bonesGenitals = []
    
    for ctrl in rawBonesGenitals:
        bonesGenitals.append(sfmUtils.FindFirstDag( [ str(ctrl.name)], True ))
    
    #==============================================================================================
    # Create the rig handles and constrain them to existing bones
    #==============================================================================================
    rigRoot    = sfmUtils.CreateConstrainedHandle( "rig_root",     boneRoot,    bCreateControls=False )
    rigPelvis  = sfmUtils.CreateConstrainedHandle( "rig_pelvis",   bonePelvis,  bCreateControls=False )
    rigSpine0  = sfmUtils.CreateConstrainedHandle( "rig_spine_0",  boneSpine0,  bCreateControls=False )
    rigSpine1  = sfmUtils.CreateConstrainedHandle( "rig_spine_1",  boneSpine1,  bCreateControls=False )
    rigSpine2  = sfmUtils.CreateConstrainedHandle( "rig_spine_2",  boneSpine2,  bCreateControls=False )
    rigChest  = sfmUtils.CreateConstrainedHandle( "rig_chest",  boneSpine3,  bCreateControls=False )
    rigNeck1    = sfmUtils.CreateConstrainedHandle( "rig_neck",     boneNeck1,    bCreateControls=False )
    rigHead    = sfmUtils.CreateConstrainedHandle( "rig_head",     boneHead,    bCreateControls=False )
    
    rigFootR   = sfmUtils.CreateConstrainedHandle( "rig_foot_R",   boneFootR,   bCreateControls=False )
    rigToeR    = sfmUtils.CreateConstrainedHandle( "rig_toe_R",    boneToeR,    bCreateControls=False )
    rigCollarR = sfmUtils.CreateConstrainedHandle( "rig_collar_R", boneCollarR, bCreateControls=False )
    rigHandR   = sfmUtils.CreateConstrainedHandle( "rig_hand_R",   boneHandR,   bCreateControls=False )
    rigFootL   = sfmUtils.CreateConstrainedHandle( "rig_foot_L",   boneFootL,   bCreateControls=False )
    rigToeL    = sfmUtils.CreateConstrainedHandle( "rig_toe_L",    boneToeL,    bCreateControls=False )
    rigCollarL = sfmUtils.CreateConstrainedHandle( "rig_collar_L", boneCollarL, bCreateControls=False )
    rigHandL   = sfmUtils.CreateConstrainedHandle( "rig_hand_L",   boneHandL,   bCreateControls=False ) 
    
    rigFinger00r   = sfmUtils.CreateConstrainedHandle( "rig_finger00_r",   boneFinger00r,   bCreateControls=False )
    rigFinger01r   = sfmUtils.CreateConstrainedHandle( "rig_finger01_r",   boneFinger01r,   bCreateControls=False )
    rigFinger02r   = sfmUtils.CreateConstrainedHandle( "rig_finger02_r",   boneFinger02r,   bCreateControls=False )
    rigFinger10r   = sfmUtils.CreateConstrainedHandle( "rig_finger10_r",   boneFinger10r,   bCreateControls=False )
    rigFinger11r   = sfmUtils.CreateConstrainedHandle( "rig_finger11_r",   boneFinger11r,   bCreateControls=False )
    rigFinger12r   = sfmUtils.CreateConstrainedHandle( "rig_finger12_r",   boneFinger12r,   bCreateControls=False )
    rigFinger20r   = sfmUtils.CreateConstrainedHandle( "rig_finger20_r",   boneFinger20r,   bCreateControls=False )
    rigFinger21r   = sfmUtils.CreateConstrainedHandle( "rig_finger21_r",   boneFinger21r,   bCreateControls=False )
    rigFinger22r   = sfmUtils.CreateConstrainedHandle( "rig_finger22_r",   boneFinger22r,   bCreateControls=False )
    rigFinger30r   = sfmUtils.CreateConstrainedHandle( "rig_finger30_r",   boneFinger30r,   bCreateControls=False )
    rigFinger31r   = sfmUtils.CreateConstrainedHandle( "rig_finger31_r",   boneFinger31r,   bCreateControls=False )
    rigFinger32r   = sfmUtils.CreateConstrainedHandle( "rig_finger32_r",   boneFinger32r,   bCreateControls=False )
    rigFinger40r   = sfmUtils.CreateConstrainedHandle( "rig_finger40_r",   boneFinger40r,   bCreateControls=False )
    rigFinger41r   = sfmUtils.CreateConstrainedHandle( "rig_finger41_r",   boneFinger41r,   bCreateControls=False )
    rigFinger42r   = sfmUtils.CreateConstrainedHandle( "rig_finger42_r",   boneFinger42r,   bCreateControls=False )
    
    rigFinger00l   = sfmUtils.CreateConstrainedHandle( "rig_finger00_l",   boneFinger00l,   bCreateControls=False )
    rigFinger01l   = sfmUtils.CreateConstrainedHandle( "rig_finger01_l",   boneFinger01l,   bCreateControls=False )
    rigFinger02l   = sfmUtils.CreateConstrainedHandle( "rig_finger02_l",   boneFinger02l,   bCreateControls=False )
    rigFinger10l   = sfmUtils.CreateConstrainedHandle( "rig_finger10_l",   boneFinger10l,   bCreateControls=False )
    rigFinger11l   = sfmUtils.CreateConstrainedHandle( "rig_finger11_l",   boneFinger11l,   bCreateControls=False )
    rigFinger12l   = sfmUtils.CreateConstrainedHandle( "rig_finger12_l",   boneFinger12l,   bCreateControls=False )
    rigFinger20l   = sfmUtils.CreateConstrainedHandle( "rig_finger20_l",   boneFinger20l,   bCreateControls=False )
    rigFinger21l   = sfmUtils.CreateConstrainedHandle( "rig_finger21_l",   boneFinger21l,   bCreateControls=False )
    rigFinger22l   = sfmUtils.CreateConstrainedHandle( "rig_finger22_l",   boneFinger22l,   bCreateControls=False )
    rigFinger30l   = sfmUtils.CreateConstrainedHandle( "rig_finger30_l",   boneFinger30l,   bCreateControls=False )
    rigFinger31l   = sfmUtils.CreateConstrainedHandle( "rig_finger31_l",   boneFinger31l,   bCreateControls=False )
    rigFinger32l   = sfmUtils.CreateConstrainedHandle( "rig_finger32_l",   boneFinger32l,   bCreateControls=False )
    rigFinger40l   = sfmUtils.CreateConstrainedHandle( "rig_finger40_l",   boneFinger40l,   bCreateControls=False )
    rigFinger41l   = sfmUtils.CreateConstrainedHandle( "rig_finger41_l",   boneFinger41l,   bCreateControls=False )
    rigFinger42l   = sfmUtils.CreateConstrainedHandle( "rig_finger42_l",   boneFinger42l,   bCreateControls=False )
	
    rigToe00r   = sfmUtils.CreateConstrainedHandle( "rig_toe00_r",   boneToe00r,   bCreateControls=False )
    rigToe01r   = sfmUtils.CreateConstrainedHandle( "rig_toe01_r",   boneToe01r,   bCreateControls=False )
    rigToe10r   = sfmUtils.CreateConstrainedHandle( "rig_toe10_r",   boneToe10r,   bCreateControls=False )
    rigToe11r   = sfmUtils.CreateConstrainedHandle( "rig_toe11_r",   boneToe11r,   bCreateControls=False )
    rigToe20r   = sfmUtils.CreateConstrainedHandle( "rig_toe20_r",   boneToe20r,   bCreateControls=False )
    rigToe21r   = sfmUtils.CreateConstrainedHandle( "rig_toe21_r",   boneToe21r,   bCreateControls=False )
    rigToe30r   = sfmUtils.CreateConstrainedHandle( "rig_toe30_r",   boneToe30r,   bCreateControls=False )
    rigToe31r   = sfmUtils.CreateConstrainedHandle( "rig_toe31_r",   boneToe31r,   bCreateControls=False )
    rigToe40r   = sfmUtils.CreateConstrainedHandle( "rig_toe40_r",   boneToe40r,   bCreateControls=False )
    rigToe41r   = sfmUtils.CreateConstrainedHandle( "rig_toe41_r",   boneToe41r,   bCreateControls=False )
    
    rigToe00l   = sfmUtils.CreateConstrainedHandle( "rig_toe00_l",   boneToe00l,   bCreateControls=False )
    rigToe01l   = sfmUtils.CreateConstrainedHandle( "rig_toe01_l",   boneToe01l,   bCreateControls=False )
    rigToe10l   = sfmUtils.CreateConstrainedHandle( "rig_toe10_l",   boneToe10l,   bCreateControls=False )
    rigToe11l   = sfmUtils.CreateConstrainedHandle( "rig_toe11_l",   boneToe11l,   bCreateControls=False )
    rigToe20l   = sfmUtils.CreateConstrainedHandle( "rig_toe20_l",   boneToe20l,   bCreateControls=False )
    rigToe21l   = sfmUtils.CreateConstrainedHandle( "rig_toe21_l",   boneToe21l,   bCreateControls=False )
    rigToe30l   = sfmUtils.CreateConstrainedHandle( "rig_toe30_l",   boneToe30l,   bCreateControls=False )
    rigToe31l   = sfmUtils.CreateConstrainedHandle( "rig_toe31_l",   boneToe31l,   bCreateControls=False )
    rigToe40l   = sfmUtils.CreateConstrainedHandle( "rig_toe40_l",   boneToe40l,   bCreateControls=False )
    rigToe41l   = sfmUtils.CreateConstrainedHandle( "rig_toe41_l",   boneToe41l,   bCreateControls=False )
        
    
    # Use the direction from the heel to the toe to compute the knee offsets, 
    # this makes the knee offset indpendent of the inital orientation of the model.
    vKneeOffsetR = ComputeVectorBetweenBones( boneFootR, boneToeR, 10 )
    vKneeOffsetL = ComputeVectorBetweenBones( boneFootL, boneToeL, 10 )
    
    rigKneeR   = sfmUtils.CreateOffsetHandle( "rig_knee_R",  boneLowerLegR, vKneeOffsetR,  bCreateControls=False )   
    rigKneeL   = sfmUtils.CreateOffsetHandle( "rig_knee_L",  boneLowerLegL, vKneeOffsetL,  bCreateControls=False )
    rigElbowR  = sfmUtils.CreateOffsetHandle( "rig_elbow_R", boneLowerArmR, -vKneeOffsetR,  bCreateControls=False )
    rigElbowL  = sfmUtils.CreateOffsetHandle( "rig_elbow_L", boneLowerArmL, -vKneeOffsetL,  bCreateControls=False )
    
    # Create a helper handle which will remain constrained to the each foot position that can be used for parenting.
    rigFootHelperR = sfmUtils.CreateConstrainedHandle( "rig_footHelper_R", boneFootR, bCreateControls=False )
    rigFootHelperL = sfmUtils.CreateConstrainedHandle( "rig_footHelper_L", boneFootL, bCreateControls=False )
    
    # Create a list of all of the rig dags
    allRigHandles = [ rigRoot, rigPelvis, rigSpine0, rigSpine1, rigSpine2, rigChest, rigNeck1, rigHead,
                      rigCollarR, rigElbowR, rigHandR, rigKneeR, rigFootR, rigToeR,
                      rigCollarL, rigElbowL, rigHandL, rigKneeL, rigFootL, rigToeL,
                      rigFinger00r, rigFinger01r, rigFinger02r,
                      rigFinger10r, rigFinger11r, rigFinger12r,
                      rigFinger20r, rigFinger21r, rigFinger22r,
                      rigFinger30r, rigFinger31r, rigFinger32r,
                      rigFinger40r, rigFinger41r, rigFinger42r,
                      rigFinger00l, rigFinger01l, rigFinger02l,
                      rigFinger10l, rigFinger11l, rigFinger12l,
                      rigFinger20l, rigFinger21l, rigFinger22l,
                      rigFinger30l, rigFinger31l, rigFinger32l,
                      rigFinger40l, rigFinger41l, rigFinger42l,
                      rigToe00r, rigToe01r,
                      rigToe10r, rigToe11r,
                      rigToe20r, rigToe21r,
                      rigToe30r, rigToe31r,
                      rigToe40r, rigToe41r,
                      rigToe00l, rigToe01l,
                      rigToe10l, rigToe11l,
                      rigToe20l, rigToe21l,
                      rigToe30l, rigToe31l,
                      rigToe40l, rigToe41l ];
    
    
    #==============================================================================================
    # Generate the world space logs for the rig handles and remove the constraints
    #==============================================================================================
    sfm.ClearSelection()
    sfmUtils.SelectDagList( allRigHandles )
    sfm.GenerateSamples()
    sfm.RemoveConstraints()    
    
    
    #==============================================================================================
    # Build the rig handle hierarchy
    #==============================================================================================
    sfmUtils.ParentMaintainWorld( rigPelvis,        rigRoot )
    sfmUtils.ParentMaintainWorld( rigSpine0,        rigPelvis )
    sfmUtils.ParentMaintainWorld( rigSpine1,        rigSpine0 )
    sfmUtils.ParentMaintainWorld( rigSpine2,        rigSpine1 )
    sfmUtils.ParentMaintainWorld( rigChest,        rigSpine2 )
    sfmUtils.ParentMaintainWorld( rigNeck1,          rigChest )
    sfmUtils.ParentMaintainWorld( rigHead,          rigNeck1 )
    
    sfmUtils.ParentMaintainWorld( rigFootHelperR,   rigRoot )
    sfmUtils.ParentMaintainWorld( rigFootHelperL,   rigRoot )
    sfmUtils.ParentMaintainWorld( rigFootR,         rigRoot )
    sfmUtils.ParentMaintainWorld( rigFootL,         rigRoot )
    sfmUtils.ParentMaintainWorld( rigKneeR,         rigFootR )
    sfmUtils.ParentMaintainWorld( rigKneeL,         rigFootL )
    sfmUtils.ParentMaintainWorld( rigToeR,          rigFootHelperR )
    sfmUtils.ParentMaintainWorld( rigToeL,          rigFootHelperL )
    
    sfmUtils.ParentMaintainWorld( rigCollarR,       rigChest )
    sfmUtils.ParentMaintainWorld( rigElbowR,        rigCollarR )
    sfmUtils.ParentMaintainWorld( rigHandR,	    rigRoot )
    sfmUtils.ParentMaintainWorld( rigCollarL,       rigChest )
    sfmUtils.ParentMaintainWorld( rigElbowL,        rigCollarL )
    sfmUtils.ParentMaintainWorld( rigHandL,	    rigRoot )
    
    sfmUtils.ParentMaintainWorld( rigFinger00r,	    boneHandR )
    sfmUtils.ParentMaintainWorld( rigFinger01r,	    rigFinger00r )
    sfmUtils.ParentMaintainWorld( rigFinger02r,	    rigFinger01r )
    sfmUtils.ParentMaintainWorld( rigFinger10r,	    boneHandR )
    sfmUtils.ParentMaintainWorld( rigFinger11r,	    rigFinger10r )
    sfmUtils.ParentMaintainWorld( rigFinger12r,	    rigFinger11r )
    sfmUtils.ParentMaintainWorld( rigFinger20r,	    boneHandR )
    sfmUtils.ParentMaintainWorld( rigFinger21r,	    rigFinger20r )
    sfmUtils.ParentMaintainWorld( rigFinger22r,	    rigFinger21r )
    sfmUtils.ParentMaintainWorld( rigFinger30r,	    boneHandR )
    sfmUtils.ParentMaintainWorld( rigFinger31r,	    rigFinger30r )
    sfmUtils.ParentMaintainWorld( rigFinger32r,	    rigFinger31r )
    sfmUtils.ParentMaintainWorld( rigFinger40r,	    boneHandR )
    sfmUtils.ParentMaintainWorld( rigFinger41r,	    rigFinger40r )
    sfmUtils.ParentMaintainWorld( rigFinger42r,	    rigFinger41r )
    
    sfmUtils.ParentMaintainWorld( rigFinger00l,	    boneHandL )
    sfmUtils.ParentMaintainWorld( rigFinger01l,	    rigFinger00l )
    sfmUtils.ParentMaintainWorld( rigFinger02l,	    rigFinger01l )
    sfmUtils.ParentMaintainWorld( rigFinger10l,	    boneHandL )
    sfmUtils.ParentMaintainWorld( rigFinger11l,	    rigFinger10l )
    sfmUtils.ParentMaintainWorld( rigFinger12l,	    rigFinger11l )
    sfmUtils.ParentMaintainWorld( rigFinger20l,	    boneHandL )
    sfmUtils.ParentMaintainWorld( rigFinger21l,	    rigFinger20l )
    sfmUtils.ParentMaintainWorld( rigFinger22l,	    rigFinger21l )
    sfmUtils.ParentMaintainWorld( rigFinger30l,	    boneHandL )
    sfmUtils.ParentMaintainWorld( rigFinger31l,	    rigFinger30l )
    sfmUtils.ParentMaintainWorld( rigFinger32l,	    rigFinger31l )
    sfmUtils.ParentMaintainWorld( rigFinger40l,	    boneHandL )
    sfmUtils.ParentMaintainWorld( rigFinger41l,	    rigFinger40l )
    sfmUtils.ParentMaintainWorld( rigFinger42l,	    rigFinger41l )
	
    sfmUtils.ParentMaintainWorld( rigToe00r,	    boneToeR )
    sfmUtils.ParentMaintainWorld( rigToe01r,	    rigToe00r )
    sfmUtils.ParentMaintainWorld( rigToe10r,	    boneToeR )
    sfmUtils.ParentMaintainWorld( rigToe11r,	    rigToe10r )
    sfmUtils.ParentMaintainWorld( rigToe20r,	    boneToeR )
    sfmUtils.ParentMaintainWorld( rigToe21r,	    rigToe20r )
    sfmUtils.ParentMaintainWorld( rigToe30r,	    boneToeR )
    sfmUtils.ParentMaintainWorld( rigToe31r,	    rigToe30r )
    sfmUtils.ParentMaintainWorld( rigToe40r,	    boneToeR )
    sfmUtils.ParentMaintainWorld( rigToe41r,	    rigToe40r )
    
    sfmUtils.ParentMaintainWorld( rigToe00l,	    boneToeL )
    sfmUtils.ParentMaintainWorld( rigToe01l,	    rigToe00l )
    sfmUtils.ParentMaintainWorld( rigToe10l,	    boneToeL )
    sfmUtils.ParentMaintainWorld( rigToe11l,	    rigToe10l )
    sfmUtils.ParentMaintainWorld( rigToe20l,	    boneToeL )
    sfmUtils.ParentMaintainWorld( rigToe21l,	    rigToe20l )
    sfmUtils.ParentMaintainWorld( rigToe30l,	    boneToeL )
    sfmUtils.ParentMaintainWorld( rigToe31l,	    rigToe30l )
    sfmUtils.ParentMaintainWorld( rigToe40l,	    boneToeL )
    sfmUtils.ParentMaintainWorld( rigToe41l,	    rigToe40l )
    
    # Create the hips control, this allows a pelvis rotation that does not effect the spine,
    # it is only used for rotation so a position control is not created. Additionally add the
    # new control to the selection so the that set default call operates on it too.
    print rigPelvis
    
    rigHips = sfmUtils.CreateHandleAt( "rig_hips", rigPelvis, False, True )
    sfmUtils.Parent( rigHips, rigPelvis, vs.REPARENT_LOGS_OVERWRITE )
    sfm.SelectDag( rigHips )

    # Set the defaults of the rig transforms to the current locations. Defaults are stored in local
    # space, so while the parent operation tries to preserve default values it is cleaner to just
    # set them once the final hierarchy is constructed.
    sfm.SetDefault()
    
    
    #==============================================================================================
    # Create the reverse foot controls for both the left and right foot
    #==============================================================================================
    rigLegsGroup = rootGroup.CreateControlGroup( "RigLegs" )
    rigHelpersGroup = rootGroup.CreateControlGroup( "RigHelpers" )
    rigHelpersGroup.SetVisible( False )
    rigHelpersGroup.SetSnappable( False )
    
    footIKTargetR = rigFootR
    footIkTargetL = rigFootL
    
    if ( gameModel != None ) :
        footRollIkTargetR = CreateReverseFoot( "rig_footRoll", "R", gameModel, animSet, shot, rigHelpersGroup, rigLegsGroup )
        footRollIkTargetL = CreateReverseFoot( "rig_footRoll", "L", gameModel, animSet, shot, rigHelpersGroup, rigLegsGroup )
        if ( footRollIkTargetR != None ) :
            footIKTargetR = footRollIkTargetR
        if ( footRollIkTargetL != None ) :
            footIkTargetL = footRollIkTargetL
    
    
    #==============================================================================================
    # Create constraints to drive the bone transforms using the rig handles
    #==============================================================================================
    
    # The following bones are simply constrained directly to a rig handle
    sfmUtils.CreatePointOrientConstraint( rigRoot,      boneRoot        )
    sfmUtils.CreatePointOrientConstraint( rigHips,      bonePelvis      )
    sfmUtils.CreatePointOrientConstraint( rigSpine0,    boneSpine0      )
    sfmUtils.CreatePointOrientConstraint( rigSpine1,    boneSpine1      )
    sfmUtils.CreatePointOrientConstraint( rigSpine2,    boneSpine2      )
    sfmUtils.CreatePointOrientConstraint( rigChest,    boneSpine3      )
    sfmUtils.CreatePointOrientConstraint( rigNeck1,      boneNeck1        )
    sfmUtils.CreatePointOrientConstraint( rigHead,      boneHead        )
    sfmUtils.CreatePointOrientConstraint( rigCollarR,   boneCollarR     )
    sfmUtils.CreatePointOrientConstraint( rigCollarL,   boneCollarL     )
    sfmUtils.CreatePointOrientConstraint( rigToeR,      boneToeR        )
    sfmUtils.CreatePointOrientConstraint( rigToeL,      boneToeL        )
    
    sfmUtils.CreatePointOrientConstraint( rigFinger00r,      boneFinger00r        )
    sfmUtils.CreatePointOrientConstraint( rigFinger01r,      boneFinger01r        )
    sfmUtils.CreatePointOrientConstraint( rigFinger02r,      boneFinger02r        )
    sfmUtils.CreatePointOrientConstraint( rigFinger10r,      boneFinger10r        )
    sfmUtils.CreatePointOrientConstraint( rigFinger11r,      boneFinger11r        )
    sfmUtils.CreatePointOrientConstraint( rigFinger12r,      boneFinger12r        )
    sfmUtils.CreatePointOrientConstraint( rigFinger20r,      boneFinger20r        )
    sfmUtils.CreatePointOrientConstraint( rigFinger21r,      boneFinger21r        )
    sfmUtils.CreatePointOrientConstraint( rigFinger22r,      boneFinger22r        )
    sfmUtils.CreatePointOrientConstraint( rigFinger30r,      boneFinger30r        )
    sfmUtils.CreatePointOrientConstraint( rigFinger31r,      boneFinger31r        )
    sfmUtils.CreatePointOrientConstraint( rigFinger32r,      boneFinger32r        )
    sfmUtils.CreatePointOrientConstraint( rigFinger40r,      boneFinger40r        )
    sfmUtils.CreatePointOrientConstraint( rigFinger41r,      boneFinger41r        )
    sfmUtils.CreatePointOrientConstraint( rigFinger42r,      boneFinger42r        )
    
    sfmUtils.CreatePointOrientConstraint( rigFinger00l,      boneFinger00l        )
    sfmUtils.CreatePointOrientConstraint( rigFinger01l,      boneFinger01l        )
    sfmUtils.CreatePointOrientConstraint( rigFinger02l,      boneFinger02l        )
    sfmUtils.CreatePointOrientConstraint( rigFinger10l,      boneFinger10l        )
    sfmUtils.CreatePointOrientConstraint( rigFinger11l,      boneFinger11l        )
    sfmUtils.CreatePointOrientConstraint( rigFinger12l,      boneFinger12l        )
    sfmUtils.CreatePointOrientConstraint( rigFinger20l,      boneFinger20l        )
    sfmUtils.CreatePointOrientConstraint( rigFinger21l,      boneFinger21l        )
    sfmUtils.CreatePointOrientConstraint( rigFinger22l,      boneFinger22l        )
    sfmUtils.CreatePointOrientConstraint( rigFinger30l,      boneFinger30l        )
    sfmUtils.CreatePointOrientConstraint( rigFinger31l,      boneFinger31l        )
    sfmUtils.CreatePointOrientConstraint( rigFinger32l,      boneFinger32l        )
    sfmUtils.CreatePointOrientConstraint( rigFinger40l,      boneFinger40l        )
    sfmUtils.CreatePointOrientConstraint( rigFinger41l,      boneFinger41l        )
    sfmUtils.CreatePointOrientConstraint( rigFinger42l,      boneFinger42l        )
	
    sfmUtils.CreatePointOrientConstraint( rigToe00r,      boneToe00r        )
    sfmUtils.CreatePointOrientConstraint( rigToe01r,      boneToe01r        )
    sfmUtils.CreatePointOrientConstraint( rigToe10r,      boneToe10r        )
    sfmUtils.CreatePointOrientConstraint( rigToe11r,      boneToe11r        )
    sfmUtils.CreatePointOrientConstraint( rigToe20r,      boneToe20r        )
    sfmUtils.CreatePointOrientConstraint( rigToe21r,      boneToe21r        )
    sfmUtils.CreatePointOrientConstraint( rigToe30r,      boneToe30r        )
    sfmUtils.CreatePointOrientConstraint( rigToe31r,      boneToe31r        )
    sfmUtils.CreatePointOrientConstraint( rigToe40r,      boneToe40r        )
    sfmUtils.CreatePointOrientConstraint( rigToe41r,      boneToe41r        )
    
    sfmUtils.CreatePointOrientConstraint( rigToe00l,      boneToe00l        )
    sfmUtils.CreatePointOrientConstraint( rigToe01l,      boneToe01l        )
    sfmUtils.CreatePointOrientConstraint( rigToe10l,      boneToe10l        )
    sfmUtils.CreatePointOrientConstraint( rigToe11l,      boneToe11l        )
    sfmUtils.CreatePointOrientConstraint( rigToe20l,      boneToe20l        )
    sfmUtils.CreatePointOrientConstraint( rigToe21l,      boneToe21l        )
    sfmUtils.CreatePointOrientConstraint( rigToe30l,      boneToe30l        )
    sfmUtils.CreatePointOrientConstraint( rigToe31l,      boneToe31l        )
    sfmUtils.CreatePointOrientConstraint( rigToe40l,      boneToe40l        )
    sfmUtils.CreatePointOrientConstraint( rigToe41l,      boneToe41l        )
    
    # Create ik constraints for the arms and legs that will control the rotation of the hip / knee and 
    # upper arm / elbow joints based on the position of the foot and hand respectively.
    sfmUtils.BuildArmLeg( rigKneeR,  footIKTargetR, boneUpperLegR,  boneFootR, True )
    sfmUtils.BuildArmLeg( rigKneeL,  footIkTargetL, boneUpperLegL,  boneFootL, True )
    sfmUtils.BuildArmLeg( rigElbowR, rigHandR,      boneUpperArmR,  boneHandR, True )
    sfmUtils.BuildArmLeg( rigElbowL, rigHandL,      boneUpperArmL,  boneHandL, True )
    
    
    #==============================================================================================
    # Create handles for the important attachment points 
    #==============================================================================================    
    attachmentGroup = rootGroup.CreateControlGroup( "Attachments" )  
    attachmentGroup.SetVisible( False )
    
    sfmUtils.CreateAttachmentHandleInGroup( "pvt_heel_R",       attachmentGroup )
    sfmUtils.CreateAttachmentHandleInGroup( "pvt_toe_R",        attachmentGroup )
    sfmUtils.CreateAttachmentHandleInGroup( "pvt_outerFoot_R",  attachmentGroup )
    sfmUtils.CreateAttachmentHandleInGroup( "pvt_innerFoot_R",  attachmentGroup )
    
    sfmUtils.CreateAttachmentHandleInGroup( "pvt_heel_L",       attachmentGroup )
    sfmUtils.CreateAttachmentHandleInGroup( "pvt_toe_L",        attachmentGroup )
    sfmUtils.CreateAttachmentHandleInGroup( "pvt_outerFoot_L",  attachmentGroup )
    sfmUtils.CreateAttachmentHandleInGroup( "pvt_innerFoot_L",  attachmentGroup )
    
    
    
    #==============================================================================================
    # Re-organize the selection groups
    #==============================================================================================  
    rigBodyGroup = rootGroup.CreateControlGroup( "RigBody" )
    rigArmsGroup = rootGroup.CreateControlGroup( "RigArms" )
    
    RightArmGroup = rootGroup.CreateControlGroup( "RightArm" )
    LeftArmGroup = rootGroup.CreateControlGroup( "LeftArm" )
    RightLegGroup = rootGroup.CreateControlGroup( "RightLeg" )
    LeftLegGroup = rootGroup.CreateControlGroup( "LeftLeg" )   
    
    RightArmTwistGroup = rootGroup.CreateControlGroup( "Twist" )
    RightLegTwistGroup = rootGroup.CreateControlGroup( "Twist " )
    LeftArmTwistGroup = rootGroup.CreateControlGroup( "Twist  " )
    LeftLegTwistGroup = rootGroup.CreateControlGroup( "Twist   " )
    
    RightHandAttachGroup = rootGroup.CreateControlGroup( "Attach Points" )
    LeftHandAttachGroup = rootGroup.CreateControlGroup( "Attach Points " )
    RightFootAttachGroup = rootGroup.CreateControlGroup( "Attach Points  " )
    LeftFootAttachGroup = rootGroup.CreateControlGroup( "Attach Points   " )
    
    BreastsGroup = rootGroup.CreateControlGroup( "Breasts" )
    ButtGroup = rootGroup.CreateControlGroup( "Butt" )
    GenitalsGroup = rootGroup.CreateControlGroup( "Genitals" )
    
    RightFingersGroup = rootGroup.CreateControlGroup( "RightFingers" )
    LeftFingersGroup = rootGroup.CreateControlGroup( "LeftFingers" )
    RightToesGroup = rootGroup.CreateControlGroup( "RightToes" )
    LeftToesGroup = rootGroup.CreateControlGroup( "LeftToes" )
    
    sfmUtils.AddDagControlsToGroup( rigBodyGroup, rigRoot, rigPelvis, rigHips, rigSpine0, rigSpine1, rigSpine2, rigChest, rigNeck1, rigHead )  
      
    rigBodyGroup.AddChild( BreastsGroup )
    rigBodyGroup.AddChild( ButtGroup )
    rigBodyGroup.AddChild( GenitalsGroup )
    
    sfmUtils.AddDagControlsToGroup( BreastsGroup, boneBreastRootR, boneBreast0R, boneBreast1R, boneBreast2R, boneBreastRootL, boneBreast0L, boneBreast1L, boneBreast2L )
    sfmUtils.AddDagControlsToGroup( ButtGroup, boneButt0R, boneButt1R, boneButt0L, boneButt1L )
    sfmUtils.AddDagControlsToGroup( GenitalsGroup, *bonesGenitals ) 
    
    rigArmsGroup.AddChild( RightArmGroup )
    rigArmsGroup.AddChild( LeftArmGroup )
    sfmUtils.AddDagControlsToGroup( RightArmGroup,  rigHandR, rigElbowR, rigCollarR )
    sfmUtils.AddDagControlsToGroup( LeftArmGroup, rigHandL, rigElbowL, rigCollarL )
    
    RightArmGroup.AddChild( RightArmTwistGroup )
    sfmUtils.AddDagControlsToGroup( RightArmTwistGroup, boneCollarTwistR, boneUpperArmTwist1R, boneUpperArmTwist2R, boneLowerArmTwist1R, boneLowerArmTwist2R )
    
    
    RightArmGroup.AddChild( RightHandAttachGroup )
    sfmUtils.AddDagControlsToGroup( RightHandAttachGroup, boneHandR )
    
    LeftArmGroup.AddChild( LeftArmTwistGroup )
    sfmUtils.AddDagControlsToGroup( LeftArmTwistGroup, boneCollarTwistL, boneUpperArmTwist1L, boneUpperArmTwist2L, boneLowerArmTwist1L, boneLowerArmTwist2L )
    
    LeftArmGroup.AddChild( LeftHandAttachGroup )
    sfmUtils.AddDagControlsToGroup( LeftHandAttachGroup, boneHandL )
    
    rigLegsGroup.AddChild( RightLegGroup )
    rigLegsGroup.AddChild( LeftLegGroup )
    sfmUtils.AddDagControlsToGroup( RightLegGroup, rigKneeR, rigFootR, rigToeR )
    sfmUtils.AddDagControlsToGroup( LeftLegGroup, rigKneeL, rigFootL, rigToeL )
    
    RightLegGroup.AddChild( RightLegTwistGroup )
    sfmUtils.AddDagControlsToGroup( RightLegTwistGroup, boneUpperLegTwist1R, boneLowerLegTwistR, boneFootTwistR )    
    
    RightLegGroup.AddChild( RightFootAttachGroup )
    sfmUtils.AddDagControlsToGroup( RightFootAttachGroup, boneFootR )
    
    LeftLegGroup.AddChild( LeftLegTwistGroup )
    sfmUtils.AddDagControlsToGroup( LeftLegTwistGroup, boneUpperLegTwist1L, boneLowerLegTwistL, boneFootTwistL )
    
    LeftLegGroup.AddChild( LeftFootAttachGroup )
    sfmUtils.AddDagControlsToGroup( LeftFootAttachGroup, boneFootL )
    
    RightArmGroup.AddChild( RightFingersGroup )
    sfmUtils.AddDagControlsToGroup( RightFingersGroup, rigFinger00r, rigFinger01r, rigFinger02r, rigFinger10r, rigFinger11r, rigFinger12r, rigFinger20r, rigFinger21r, rigFinger22r, rigFinger30r, rigFinger31r, rigFinger32r, rigFinger40r, rigFinger41r, rigFinger42r )
    
    LeftArmGroup.AddChild( LeftFingersGroup )
    sfmUtils.AddDagControlsToGroup( LeftFingersGroup, rigFinger00l, rigFinger01l, rigFinger02l, rigFinger10l, rigFinger11l, rigFinger12l, rigFinger20l, rigFinger21l, rigFinger22l, rigFinger30l, rigFinger31l, rigFinger32l, rigFinger40l, rigFinger41l, rigFinger42l )
	
    RightLegGroup.AddChild( RightToesGroup )
    sfmUtils.AddDagControlsToGroup( RightToesGroup, rigToe00r, rigToe01r, rigToe10r, rigToe11r, rigToe20r, rigToe21r, rigToe30r, rigToe31r, rigToe40r, rigToe41r )
    
    LeftLegGroup.AddChild( LeftToesGroup )
    sfmUtils.AddDagControlsToGroup( LeftToesGroup, rigToe00l, rigToe01l, rigToe10l, rigToe11l, rigToe20l, rigToe21l, rigToe30l, rigToe31l, rigToe40l, rigToe41l )    
    
    sfmUtils.MoveControlGroup( "rig_footRoll_L", rigLegsGroup, LeftLegGroup )
    sfmUtils.MoveControlGroup( "rig_footRoll_R", rigLegsGroup, RightLegGroup )
 
    sfmUtils.AddDagControlsToGroup( rigHelpersGroup, rigFootHelperR, rigFootHelperL )

    # Set the control group visiblity, this is done through the rig so it can track which
    # groups it hid, so they can be set back to being visible when the rig is detached.
    HideControlGroups( rig, rootGroup, "Body", "Arms", "Legs", "Unknown", "Other", "Root" )      
        
    #Re-order the groups
    fingersGroup = rootGroup.FindChildByName( "Fingers", False ) 
    rootGroup.MoveChildToBottom( rigBodyGroup )
    rootGroup.MoveChildToBottom( rigLegsGroup )    
    rootGroup.MoveChildToBottom( rigArmsGroup )      
        

    #==============================================================================================
    # Set the selection groups colors
    #==============================================================================================
    topLevelColor = vs.Color( 0, 128, 255, 255 )
    RightColor = vs.Color( 255, 0, 0, 255 )
    LeftColor = vs.Color( 0, 255, 0, 255 )
    RightColorSoft = vs.Color( 200, 60, 60, 255 )
    LeftColorSoft = vs.Color( 60, 200, 60, 255 )
    TwistColor = vs.Color( 70, 160, 160, 255 )
    AttachColor = vs.Color( 160, 160, 70, 255 )
    SexyColor = vs.Color( 240, 170, 245, 255 )
    
    rigBodyGroup.SetGroupColor( topLevelColor, False )
    rigArmsGroup.SetGroupColor( topLevelColor, False )
    rigLegsGroup.SetGroupColor( topLevelColor, False )
    attachmentGroup.SetGroupColor( topLevelColor, False )
    rigHelpersGroup.SetGroupColor( topLevelColor, False )
    
    RightArmGroup.SetGroupColor( RightColor, False )
    LeftArmGroup.SetGroupColor( LeftColor, False )
    RightLegGroup.SetGroupColor( RightColor, False )
    LeftLegGroup.SetGroupColor( LeftColor, False )
    
    RightArmTwistGroup.SetGroupColor( TwistColor, False )
    RightLegTwistGroup.SetGroupColor( TwistColor, False )
    LeftArmTwistGroup.SetGroupColor( TwistColor, False )
    LeftLegTwistGroup.SetGroupColor( TwistColor, False )
    
    RightFingersGroup.SetGroupColor( RightColorSoft, False )
    LeftFingersGroup.SetGroupColor( LeftColorSoft, False )
    RightToesGroup.SetGroupColor( RightColorSoft, False )
    LeftToesGroup.SetGroupColor( LeftColorSoft, False )
    
    BreastsGroup.SetGroupColor( TwistColor, False )
    ButtGroup.SetGroupColor( TwistColor, False )
    GenitalsGroup.SetGroupColor( SexyColor, False )
    
    RightHandAttachGroup.SetGroupColor( AttachColor, False )
    LeftHandAttachGroup.SetGroupColor( AttachColor, False )
    RightFootAttachGroup.SetGroupColor( AttachColor, False )
    LeftFootAttachGroup.SetGroupColor( AttachColor, False )    
    # End the rig definition
    sfm.EndRig()
    return
    
#==================================================================================================
# Script entry
#==================================================================================================

# Construct the rig for the selected animation set
BuildRig();


    
    




