Python parentConstraint issue

Python parentConstraint issue

Liee
Contributor Contributor
2,419 Views
6 Replies
Message 1 of 7

Python parentConstraint issue

Liee
Contributor
Contributor

Hi everyone, 

I'm currently going back to scripting in order to earn time on my rigs.
So I tried to make a quick Python rig to place my controllers on selected joints and add a parentConstraint.
Unfortunatly all the constraints appear but only the last one is functional.
May someone help me to find a solution ?

Here is my script :

targetJoints = cmds.ls( sl=1 , typ='joint' )

for targetJoint in targetJoints :

        cmds.circle( c=(0, offsetY, 0) , nr=nr , sw=360 , r=radius , ch=0 , n= "ctrl_bone");
        
    # parent shape
        
        cmds.group ( n= "grp_ctrl_bone" , em=1)

        cmds.parent ( "ctrl_bone" , "grp_ctrl_bone" , r=1 )

        cmds.parent ( "grp_ctrl_bone" , targetJoint , r=1 )

        cmds.parent ( "grp_ctrl_bone" , w=1 , r=0 )

        
    # constraint

        cmds.parentConstraint ( "ctrl_bone" , targetJoint, mo=1)



    # rename group

        grp_ctrl_bone = cmds.rename( "grp_ctrl_bone" , 'grp_' + targetJoint)
        
        cmds.rename( "ctrl_bone" , 'ctrl_' + targetJoint )

 

 

0 Likes
Accepted solutions (1)
2,420 Views
6 Replies
Replies (6)
Message 2 of 7

Martin_L_A
Contributor
Contributor
Accepted solution

Hi Liee,

 

In your code example it looks like you're looping over your joints, and for every loop you're creating a controller. However, you are not changing the name of the controller, which makes that maya tries to create a controller with the same name every time, except that by default, maya does not accept multiple objects with the same name, which means it is adding a digit at the end of the new controller's name, which is probably what you are expecting.

The problem arises when you are trying to create the parent constraint, because you are not changing your controller's name here either, which means for every loop, you are constraining the first controller created (the only one that is actually named 'ctrl_bone') to the current joint.

I would suggest either iterating over your list with the enumerate method, or with an incremented number, which would allow you to create custom names, or storing the name of the controller created in a variable in order to reuse it later (or a combination of both).

Incremented method :

targetJoints = cmds.ls( sl=1 , typ='joint' )

ctrl_number = 1
for targetJoint in targetJoints :
        ctrl_name = 'ctrl_bone' + str(ctrl_number)
        cmds.circle( c=(0, offsetY, 0) , nr=nr , sw=360 , r=radius , ch=0 , n=ctrl_name);
        
    # parent shape
        grp_ctrl_name = 'grp_' + ctrl_name
        cmds.group ( n= grp_ctrl_name , em=1)

        cmds.parent (ctrl_name , grp_ctrl_name , r=1 )

        cmds.parent ( grp_ctrl_name , targetJoint , r=1 )

        cmds.parent ( grp_ctrl_name , w=1 , r=0 )

        
    # constraint

        cmds.parentConstraint ( ctrl_name , targetJoint, mo=1)

 

enumerate method:

targetJoints = cmds.ls( sl=1 , typ='joint' )

for i, targetJoint in enumerate(targetJoints) :
        ctrl_number = i+1
        ctrl_name = 'ctrl_bone' + str(ctrl_number)
        cmds.circle( c=(0, offsetY, 0) , nr=nr , sw=360 , r=radius , ch=0 , n=ctrl_name);
        
    # parent shape
        grp_ctrl_name = 'grp_' + ctrl_name
        cmds.group ( n= grp_ctrl_name , em=1)

        cmds.parent (ctrl_name , grp_ctrl_name , r=1 )

        cmds.parent ( grp_ctrl_name , targetJoint , r=1 )

        cmds.parent ( grp_ctrl_name , w=1 , r=0 )

        
    # constraint

        cmds.parentConstraint ( ctrl_name , targetJoint, mo=1)

 

storing name in variables:

targetJoints = cmds.ls( sl=1 , typ='joint' )

for targetJoint in targetJoints :

        ctrl_name = cmds.circle( c=(0, offsetY, 0) , nr=nr , sw=360 , r=radius , ch=0 , n= "ctrl_bone");
        
    # parent shape
        
        grp_name = cmds.group ( n= "grp_ctrl_bone" , em=1)

        cmds.parent ( ctrl_name , grp_name , r=1 )

        cmds.parent ( grp_name, targetJoint , r=1 )

        cmds.parent ( grp_name , w=1 , r=0 )

        
    # constraint

        cmds.parentConstraint ( ctrl_name , targetJoint, mo=1)



    # rename group

        grp_ctrl_bone = cmds.rename(grp_name , 'grp_' + targetJoint)
        
        cmds.rename( ctrl_name , 'ctrl_' + targetJoint )

 

 

In your case, the cleanest would probably be :

targetJoints = cmds.ls( sl=True , typ='joint' )

for targetJoint in targetJoints :
        ctrl_name = 'ctrl_' + targetJoint
        grp_name = 'grp_' + targetJoint

        # storing the actual name in a variable, in case there is already something named like that in the scene
        ctrl_name = cmds.circle( c=(0, offsetY, 0) , nr=nr , sw=360 , r=radius , ch=False , n= ctrl_name);
        
    # parent shape
        
        cmds.group ( n=grp_name, r=True) # without the em flag turned on, it will parent the circle you just created in the newly created group, removing one step

        cmds.parent ( grp_name , targetJoint , r=True )

        cmds.parent ( grp_name , w=True , r=False )

        
    # constraint

        cmds.parentConstraint ( ctrl_name , targetJoint, mo=True)

It is generally good practice to use the python keywords True and False for booleans instead of numbers, as it makes more obvious what is an actual number against what is a bool.

It is also usually good to use long names for flags as it makes it more obvious for the next person who will read your code (probably you, 6 months down the line, and you will thank yourself for using long names ^^)

0 Likes
Message 3 of 7

Liee
Contributor
Contributor

Hi lantonmartin,
Thank you for the advices, I'll keep them in mind indeed.
And also thank you for the optimization, need to take the habit of making variables more often.

Unfortunately, your code has the same issue as mine, only the last controler constraints its bone.
The others have the parent constraint well assigned but it's not effective..

Any idea ?

0 Likes
Message 4 of 7

Martin_L_A
Contributor
Contributor

That is strange, that code works well on my computer, as well as at work.

Have you tried deleting your preferences? And which version of maya are you using?

0 Likes
Message 5 of 7

Liee
Contributor
Contributor

After some research, I found out that the constraints are effective (on the previous joints of the chain) however translates are working while rotating are not.
I mean, the rotation is effective on the values and local rotate axis of the joints, but the joint isn't rotating.

I reset the preferences and still the same..

I'm using maya 2018

0 Likes
Message 6 of 7

Martin_L_A
Contributor
Contributor

If you are talking about the visual representation of the joints, it only rotates when the joints orients are modified, not when you are moving the rotate x, y ,z (yes, it is very confusing).

Have you tried binding an object to your joints and then moving them with your controllers?

0 Likes
Message 7 of 7

Liee
Contributor
Contributor

No I'm talking about actual "Rotate axis" that shows how your elements are oriented.

Anyway good proposition, I just tried and je joint is well constraint, my mesh is moving.
But i just got it. And now I feel pretty studip.
Of course the parents are not moving, because the controlers aren't parented between each other..
Well, problem solved.
I'm gonna continue to study this all.
Thank you for your time and advices.