Maya Python - FK Controls generator parenting issue

I am creating a simple FK controls generator but I got stuck on a part where I need to parent each offset node under control node before it. Here’s the script so far :

import maya.cmds as mc

#create variable for the selected joints
selected = mc.ls(sl=True)

#clears the selection
mc.select(cl=True)

#create empty list for the new controls
CL = []

#for the joints in selection, run the following code
for s in selected:
    
    #create variable for the position/rotation of the joints
    pos = mc.xform(s, q=True, t=True, ws=True)
    rot = mc.xform(s, q=True, rotation=True, ws=True)
    
    #create 3lvl controls and position them on top of joints
    ctrl = mc.circle(n=str(s + '_ctrl'), radius=0.6,nr=(1,0,0), ch=False) 
    mc.group(n=str(s + '_sdk'))
    offset = mc.group(n=str(s + '_offset'))
    
    #snap the controls to the position of the joint
    mc.xform(offset, translation=pos, ws=True)
    mc.xform(offset, rotation=rot, ws=True)
    
    #parent constraint joints to ctrls
    mc.parentConstraint(ctrl, s)
    
    #append offset nodes to CL
    CL.append(offset)

   

I am fairly new to this and if you know the solution, please do your best to explain the method.

To reiterate, how do I tell Python to do this for all the controls, and in a correct order:

mc.parent(offset[1], ctrl[0])
mc.parent(offset[2], ctrl[1])
mc.parent(offset[3], ctrl[2])
mc.parent(offset[4], ctrl[3])
mc.parent(offset[5], ctrl[4])

and so on…

This looks like a job for zip():


offsets  = [......]
controls = [.....]

for offset, control in zip(offsets, controls):
      cmds.parent(offset, control)

Zip takes a bunch of lists and emits one item from each of the lists every time you loop over it. Combined with python’s ability to assign multiple values this makes a nice, natiural idiom for keeping pairs of values together. In your original you are offset by one; in this case I’m assuming you can handle that when you put together the two lists. You could also do it using a slice:


for offset, control in zip(offsets[1:] , controls):
      cmds.parent(offset, control)

which will zip the whole controls list but takes the 2nd and later objects in offsets

Note that zip will stop when either list runs out, so you’ll need to know how many items there are in each list and adjust accordingly.

[QUOTE=Theodox;28304]
Note that zip will stop when either list runs out, so you’ll need to know how many items there are in each list and adjust accordingly.
[/QUOTE]
If you do have lists that are different lengths, and need to exhaust both, itertools.izip_longest will let you define a default value that will be used for when the shorter one runs out.

I can’t get it to work. It parents offset nodes under offset nodes and I need offset nodes under CTRL nodes.

This is what I want to see:

I am new to Python, so I am sure I’m doing something wrong. Unless you spell it out for me, I will not figure it out :frowning:

Thanks

Figured it out, thanks guys

for offset, control in zip(offsets, controls[1:]):
      mc.parent(control, offset)

You can save yourself a second for loop by parenting as you create

parent = None
for s in selection:
ctrl = mc.circle()
offset = mc.group()
if parent:
mc.parent(offset, parent)
parent = ctrl