import vs

#==================================================================================================
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( [ "bip_pelvis"				], True )
    boneSpine0		= sfmUtils.FindFirstDag( [ "bip_spine_0"			], True )
    boneSpine1		= sfmUtils.FindFirstDag( [ "bip_spine_1"			], True )
    boneSpine2		= sfmUtils.FindFirstDag( [ "bip_spine_2"			], True ) 
    boneSpine3		= sfmUtils.FindFirstDag( [ "bip_spine_3"			], True )
    boneNeck		= sfmUtils.FindFirstDag( [ "bip_neck"				], True )
    boneHead		= sfmUtils.FindFirstDag( [ "bip_head"				], True )
    
    boneUpperLegR	= sfmUtils.FindFirstDag( [ "bip_hip_R"				], True )
    boneLowerLegR	= sfmUtils.FindFirstDag( [ "bip_knee_R"				], True )
    boneFootR		= sfmUtils.FindFirstDag( [ "bip_foot_R"				], True )
    boneToeR		= sfmUtils.FindFirstDag( [ "bip_toe_R"				], True ) 
    boneCollarR		= sfmUtils.FindFirstDag( [ "bip_collar_R"			], True )   
    boneUpperArmR	= sfmUtils.FindFirstDag( [ "bip_upperArm_R"			], True ) 
    boneLowerArmR	= sfmUtils.FindFirstDag( [ "bip_lowerArm_R"			], True )
    boneHandR		= sfmUtils.FindFirstDag( [ "bip_hand_R"				], True )
   
    boneUpperLegL	= sfmUtils.FindFirstDag( [ "bip_hip_L"				], True )
    boneLowerLegL	= sfmUtils.FindFirstDag( [ "bip_knee_L"				], True )
    boneFootL		= sfmUtils.FindFirstDag( [ "bip_foot_L"				], True )
    boneToeL		= sfmUtils.FindFirstDag( [ "bip_toe_L"				], True ) 
    boneCollarL		= sfmUtils.FindFirstDag( [ "bip_collar_L"			], True )   
    boneUpperArmL	= sfmUtils.FindFirstDag( [ "bip_upperArm_L"			], True ) 
    boneLowerArmL	= sfmUtils.FindFirstDag( [ "bip_lowerArm_L"			], True )
    boneHandL		= sfmUtils.FindFirstDag( [ "bip_hand_L"				], True )
	
	# Eyebrows
    boneEyebrow0L	= sfmUtils.FindFirstDag( [ "eyebrow_0_L" 			], True )
    boneEyebrow1L	= sfmUtils.FindFirstDag( [ "eyebrow_1_L" 			], True )
    boneEyebrow2L	= sfmUtils.FindFirstDag( [ "eyebrow_2_L" 			], True )
	
    boneEyebrow0R	= sfmUtils.FindFirstDag( [ "eyebrow_0_R" 			], True )
    boneEyebrow1R	= sfmUtils.FindFirstDag( [ "eyebrow_1_R" 			], True )
    boneEyebrow2R	= sfmUtils.FindFirstDag( [ "eyebrow_2_R" 			], True )
	
	# Lips
    boneLipTop0		= sfmUtils.FindFirstDag( [ "lip_top_0" 				], True )
    boneLipTop1L	= sfmUtils.FindFirstDag( [ "lip_top_1_L" 			], True )
    boneLipTop2L	= sfmUtils.FindFirstDag( [ "lip_top_2_L" 			], True )
    boneLipTop1R	= sfmUtils.FindFirstDag( [ "lip_top_1_R" 			], True )
    boneLipTop2R	= sfmUtils.FindFirstDag( [ "lip_top_2_R" 			], True )
	
    boneLipBottom0	= sfmUtils.FindFirstDag( [ "lip_bottom_0" 			], True )
    boneLipBottom1L	= sfmUtils.FindFirstDag( [ "lip_bottom_1_L" 		], True )
    boneLipBottom2L	= sfmUtils.FindFirstDag( [ "lip_bottom_2_L" 		], True )
    boneLipBottom1R	= sfmUtils.FindFirstDag( [ "lip_bottom_1_R" 		], True )
    boneLipBottom2R	= sfmUtils.FindFirstDag( [ "lip_bottom_2_R" 		], True )
	
    # Twist
    boneUATL		= sfmUtils.FindFirstDag( [ "hlp_upperArm_twist_L" 	], True )
    boneHTL			= sfmUtils.FindFirstDag( [ "hlp_hip_twist_L" 		], True )
    boneUATR		= sfmUtils.FindFirstDag( [ "hlp_upperArm_twist_R" 	], True )
    boneHTR			= sfmUtils.FindFirstDag( [ "hlp_hip_twist_R" 		], True )
	
	# Hair
    boneHair0L		= sfmUtils.FindFirstDag( [ "hair_0_L" 				], True )
    boneHair10L		= sfmUtils.FindFirstDag( [ "hair_1_0_L" 			], True )
    boneHair11L		= sfmUtils.FindFirstDag( [ "hair_1_1_L" 			], True )
    boneHair12L		= sfmUtils.FindFirstDag( [ "hair_1_2_L" 			], True )
    boneHair20L		= sfmUtils.FindFirstDag( [ "hair_2_0_L" 			], True )
    boneHair21L		= sfmUtils.FindFirstDag( [ "hair_2_1_L" 			], True )
    boneHair22L		= sfmUtils.FindFirstDag( [ "hair_2_2_L" 			], True )
	
    boneHair0R		= sfmUtils.FindFirstDag( [ "hair_0_R" 				], True )
    boneHair10R		= sfmUtils.FindFirstDag( [ "hair_1_0_R" 			], True )
    boneHair11R		= sfmUtils.FindFirstDag( [ "hair_1_1_R" 			], True )
    boneHair12R		= sfmUtils.FindFirstDag( [ "hair_1_2_R" 			], True )
    boneHair20R		= sfmUtils.FindFirstDag( [ "hair_2_0_R" 			], True )
    boneHair21R		= sfmUtils.FindFirstDag( [ "hair_2_1_R" 			], True )
    boneHair22R		= sfmUtils.FindFirstDag( [ "hair_2_2_R" 			], True )
	
	# Boob
    boneBoob0L		= sfmUtils.FindFirstDag( [ "boob_0_L"	 			], True )
    boneBoob1L		= sfmUtils.FindFirstDag( [ "boob_1_L"	 			], True )
    boneBoob2L		= sfmUtils.FindFirstDag( [ "boob_2_L"	 			], True )
	
    boneBoob0R		= sfmUtils.FindFirstDag( [ "boob_0_R"	 			], True )
    boneBoob1R		= sfmUtils.FindFirstDag( [ "boob_1_R"	 			], True )
    boneBoob2R		= sfmUtils.FindFirstDag( [ "boob_2_R"	 			], True )
	
    # Butt
    boneButtL		= sfmUtils.FindFirstDag( [ "butt_L"	 				], True )
    boneButtR		= sfmUtils.FindFirstDag( [ "butt_R"	 				], True )
	
	# Vagina
    boneVagina		= sfmUtils.FindFirstDag( [ "vagina"	 				], True )
	
    boneVagina0L	= sfmUtils.FindFirstDag( [ "vagina_0_L"				], True )
    boneVagina1L	= sfmUtils.FindFirstDag( [ "vagina_1_L"				], True )
    boneVagina2L	= sfmUtils.FindFirstDag( [ "vagina_2_L"				], True )
	
    boneVagina0R	= sfmUtils.FindFirstDag( [ "vagina_0_R"				], True )
    boneVagina1R	= sfmUtils.FindFirstDag( [ "vagina_1_R"				], True )
    boneVagina2R	= sfmUtils.FindFirstDag( [ "vagina_2_R"				], True )
	
	# Anus
    boneAnus		= sfmUtils.FindFirstDag( [ "anus"	 				], True )
	
    boneAnusL		= sfmUtils.FindFirstDag( [ "anus_L"	 				], True )
    boneAnusR		= sfmUtils.FindFirstDag( [ "anus_R"	 				], True )
    boneAnusB		= sfmUtils.FindFirstDag( [ "anus_B"	 				], True )
    boneAnusT		= sfmUtils.FindFirstDag( [ "anus_T"	 				], True )
	
	# Penis
    bonePenis0		= sfmUtils.FindFirstDag( [ "penis_0" 				], True )
    bonePenis1		= sfmUtils.FindFirstDag( [ "penis_1" 				], True )
    bonePenis2		= sfmUtils.FindFirstDag( [ "penis_2" 				], True )
    bonePenis3		= sfmUtils.FindFirstDag( [ "penis_3" 				], True )
    bonePenis4		= sfmUtils.FindFirstDag( [ "penis_4" 				], True )
	
	# Balls
    boneBalls		= sfmUtils.FindFirstDag( [ "balls" 					], True )
    boneBallL		= sfmUtils.FindFirstDag( [ "ball_L"					], True )
    boneBallR		= sfmUtils.FindFirstDag( [ "ball_R"					], True )
	
	# Toe bones
    boneToe00L		= sfmUtils.FindFirstDag( [ "toe_0_0_L"			 	], True )
    boneToe01L		= sfmUtils.FindFirstDag( [ "toe_0_1_L"			 	], True )
    boneToe10L		= sfmUtils.FindFirstDag( [ "toe_1_0_L"			 	], True )
    boneToe11L		= sfmUtils.FindFirstDag( [ "toe_1_1_L"			 	], True )
    boneToe20L		= sfmUtils.FindFirstDag( [ "toe_2_0_L"			 	], True )
    boneToe21L		= sfmUtils.FindFirstDag( [ "toe_2_1_L"			 	], True )
    boneToe30L		= sfmUtils.FindFirstDag( [ "toe_3_0_L"			 	], True )
    boneToe31L		= sfmUtils.FindFirstDag( [ "toe_3_1_L"			 	], True )
    boneToe40L		= sfmUtils.FindFirstDag( [ "toe_4_0_L"			 	], True )
    boneToe41L		= sfmUtils.FindFirstDag( [ "toe_4_1_L"			 	], True )
	
    boneToe00R		= sfmUtils.FindFirstDag( [ "toe_0_0_R"			 	], True )
    boneToe01R		= sfmUtils.FindFirstDag( [ "toe_0_1_R"			 	], True )
    boneToe10R		= sfmUtils.FindFirstDag( [ "toe_1_0_R"			 	], True )
    boneToe11R		= sfmUtils.FindFirstDag( [ "toe_1_1_R"			 	], True )
    boneToe20R		= sfmUtils.FindFirstDag( [ "toe_2_0_R"			 	], True )
    boneToe21R		= sfmUtils.FindFirstDag( [ "toe_2_1_R"			 	], True )
    boneToe30R		= sfmUtils.FindFirstDag( [ "toe_3_0_R"			 	], True )
    boneToe31R		= sfmUtils.FindFirstDag( [ "toe_3_1_R"			 	], True )
    boneToe40R		= sfmUtils.FindFirstDag( [ "toe_4_0_R"			 	], True )
    boneToe41R		= sfmUtils.FindFirstDag( [ "toe_4_1_R"			 	], 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 )
    rigNeck    = sfmUtils.CreateConstrainedHandle( "rig_neck",     boneNeck,    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 )
        
    
    # 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, rigNeck, rigHead,
                      rigCollarR, rigElbowR, rigHandR, rigKneeR, rigFootR, rigToeR,
                      rigCollarL, rigElbowL, rigHandL, rigKneeL, rigFootL, rigToeL ];
    
    
    #==============================================================================================
    # 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( rigNeck,          rigChest )
    sfmUtils.ParentMaintainWorld( rigHead,          rigNeck )
    
    # 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,          rigFootR )
    sfmUtils.ParentMaintainWorld( rigToeL,          rigFootL )
    
    sfmUtils.ParentMaintainWorld( rigCollarR,       rigChest )
    sfmUtils.ParentMaintainWorld( rigElbowR,        rigCollarR )
    sfmUtils.ParentMaintainWorld( rigHandR,	  		  rigRoot )
    sfmUtils.ParentMaintainWorld( rigCollarL,       rigChest )
    sfmUtils.ParentMaintainWorld( rigElbowL,        rigCollarL )
    sfmUtils.ParentMaintainWorld( rigHandL,	 		   rigRoot )
    
    # 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.
    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( rigNeck,      boneNeck        )
    sfmUtils.CreatePointOrientConstraint( rigHead,      boneHead        )
    sfmUtils.CreatePointOrientConstraint( rigCollarR,   boneCollarR     )
    sfmUtils.CreatePointOrientConstraint( rigCollarL,   boneCollarL     )
    sfmUtils.CreatePointOrientConstraint( rigToeR,      boneToeR        )
    sfmUtils.CreatePointOrientConstraint( rigToeL,      boneToeL        )
    
    # 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" )   

    RightToeGroup = rootGroup.CreateControlGroup( "RightToes" )
    LeftToeGroup = rootGroup.CreateControlGroup( "LeftToes" )
	
    FaceGroup = rootGroup.CreateControlGroup( "Face" )
	
    EyebrowGroup = FaceGroup.CreateControlGroup( "Eyebrows" )
    sfmUtils.AddDagControlsToGroup( EyebrowGroup, boneEyebrow0L, boneEyebrow1L, boneEyebrow2L, boneEyebrow0R, boneEyebrow1R, boneEyebrow2R)
	
    LipsGroup = FaceGroup.CreateControlGroup( "Lips" )
    sfmUtils.AddDagControlsToGroup( LipsGroup, boneLipTop0, boneLipTop1L, boneLipTop1R, boneLipTop2L, boneLipTop2R,
        boneLipBottom0, boneLipBottom1L, boneLipBottom1R, boneLipBottom2L, boneLipBottom2R )
	
    HairGroup = rootGroup.CreateControlGroup( "Hair" )
    sfmUtils.AddDagControlsToGroup( HairGroup, boneHair0L, boneHair10L, boneHair11L, boneHair12L, boneHair20L, boneHair21L, boneHair22L, 
        boneHair0R, boneHair10R, boneHair11R, boneHair12R, boneHair20R, boneHair21R, boneHair22R )
	
    BoobGroup = rootGroup.CreateControlGroup( "Boobs" )
    sfmUtils.AddDagControlsToGroup( BoobGroup, boneBoob0L, boneBoob1L, boneBoob2L, boneBoob0R, boneBoob1R, boneBoob2R )
	
    ButtGroup = rootGroup.CreateControlGroup( "Butt" )
    sfmUtils.AddDagControlsToGroup( ButtGroup, boneButtL, boneButtR )
    
    GenitalsGroup = rootGroup.CreateControlGroup( "Genitals" )
	
    VaginaGroup = GenitalsGroup.CreateControlGroup( "Vagina" )
    sfmUtils.AddDagControlsToGroup( VaginaGroup, boneVagina, boneVagina0L, boneVagina1L, boneVagina2L, boneVagina0R, boneVagina1R, boneVagina2R )
	
    AnusGroup = GenitalsGroup.CreateControlGroup( "Anus" )
    sfmUtils.AddDagControlsToGroup( AnusGroup, boneAnus, boneAnusT, boneAnusB, boneAnusL, boneAnusR )
	
    PenisGroup = GenitalsGroup.CreateControlGroup( "Penis" )
    sfmUtils.AddDagControlsToGroup( PenisGroup, bonePenis0, bonePenis1, bonePenis2, bonePenis3, bonePenis4)
	
    BallsGroup = PenisGroup.CreateControlGroup( "Balls" )
    sfmUtils.AddDagControlsToGroup( BallsGroup, boneBalls, boneBallL, boneBallR )
    
    sfmUtils.AddDagControlsToGroup( rigBodyGroup, rigRoot, rigPelvis, rigHips, rigSpine0, rigSpine1, rigSpine2, rigChest, rigNeck, rigHead )  

    rigArmsGroup.AddChild( RightArmGroup )
    rigArmsGroup.AddChild( LeftArmGroup )
    sfmUtils.AddDagControlsToGroup( RightArmGroup,  rigHandR, rigElbowR, rigCollarR, boneUATR )
    sfmUtils.AddDagControlsToGroup( LeftArmGroup, rigHandL, rigElbowL, rigCollarL , boneUATL )
    
    rigLegsGroup.AddChild( RightLegGroup )
    rigLegsGroup.AddChild( LeftLegGroup )
    sfmUtils.AddDagControlsToGroup( RightLegGroup, rigKneeR, rigFootR, rigToeR, boneHTR )
    sfmUtils.AddDagControlsToGroup( LeftLegGroup, rigKneeL, rigFootL, rigToeL, boneHTL )
    
    RightLegGroup.AddChild( RightToeGroup )
    LeftLegGroup.AddChild( LeftToeGroup )
    sfmUtils.AddDagControlsToGroup( RightToeGroup, boneToe00R, boneToe01R, boneToe10R, boneToe11R, boneToe20R, boneToe21R, boneToe30R, boneToe31R, boneToe40R, boneToe41R)
    sfmUtils.AddDagControlsToGroup( LeftToeGroup, boneToe00L, boneToe01L, boneToe10L, boneToe11L, boneToe20L, boneToe21L, boneToe30L, boneToe31L, boneToe40L, boneToe41L)
	
    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 )      
    rootGroup.MoveChildToBottom( fingersGroup )  
       
    rightFingersGroup = rootGroup.FindChildByName( "RightFingers", True ) 
    if ( rightFingersGroup != None ):
        RightArmGroup.AddChild( rightFingersGroup )
        rightFingersGroup.SetSelectable( False )
                                
    leftFingersGroup = rootGroup.FindChildByName( "LeftFingers", True ) 
    if ( leftFingersGroup != None ):
        LeftArmGroup.AddChild( leftFingersGroup )
        leftFingersGroup.SetSelectable( False )
        

    #==============================================================================================
    # 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 )
    
    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 )
    
    
    # End the rig definition
    sfm.EndRig()
    return
    
#==================================================================================================
# Script entry
#==================================================================================================

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



    
    




