Creating a master controller based off average values from multiple controllers

I am not sure if this is doable or not, but here goes…

I have created a ‘bounding box’ as a master controller that controls the rotation and translation of multiple controllers.

Currently I have been able to create the said master, by taking into account of the bounding box of the child controllers.

However I am having 2 issues.

  1. Getting the master controller to move along together with the child controllers.

Initially I tried to rectify it by getting the averaging position/ rotation of the children controllers, keyed it into the master controller followed by parenting in the child controllers thereafter. While it seems right on the first frame, as soon as I go to the next frame, the children controllers went out of control.

I have attached a scene file - here for better clarity.

This is the script that I am using to create the master controller:

cmds.select('ctrl_A', add=True)
cmds.select('ctrl_B', add=True)
selections = cmds.ls(sl=True)

master_helper = cmds.curve(
        name="masterParent", degree = 1,
        point = [(-0.5, 0.5, 0.5), (0.5, 0.5, 0.5), (0.5, 0.5, -0.5),
             (-0.5, 0.5, -0.5), (-0.5, 0.5, 0.5), (-0.5, -0.5, 0.5),
             (-0.5, -0.5, -0.5), (0.5, -0.5, -0.5), (0.5, -0.5, 0.5),
             (-0.5, -0.5, 0.5), (0.5, -0.5, 0.5), (0.5, 0.5, 0.5),
             (0.5, 0.5, -0.5), (0.5, -0.5, -0.5), (-0.5, -0.5, -0.5),
             (-0.5, 0.5, -0.5)]
    )

boundingBox = cmds.exactWorldBoundingBox(selections)
scaleX = abs(boundingBox[0] - boundingBox[3])
scaleY = abs(boundingBox[1] - boundingBox[4])
scaleZ = abs(boundingBox[2] - boundingBox[5])

cmds.xform(master_helper, scale=[scaleX, scaleY, scaleZ])

count = len(selections)
sums = [0,0,0]
for item in selections:
    pos = cmds.xform(item, q=True, rp=True, ws=True)
    sums[0] += pos[0]
    sums[1] += pos[1]
    sums[2] += pos[2]
center = [sums[0]/count, sums[1]/count, sums[2]/count]

cmds.move(center[0], center[1], center[2], master_helper)
cmds.makeIdentity(master_helper, apply=True, translate=True, rotate=True, scale=True)

cmds.parent('ctrl_A', master_helper)
cmds.parent('ctrl_B', master_helper)

And this is the averaging that I was trying to use but failing badly:

trans_sum = [0,0,0]
rots_sum = [0,0,0]
for i in selections:
    trans = cmds.xform(i, query=True, translation=True)
    rots = cmds.xform(i, query=True, rotation=True)
    
    trans_sum[0] += trans[0]
    trans_sum[1] += trans[1]
    trans_sum[2] += trans[2]
    rots_sum[0] += rots[0]
    rots_sum[1] += rots[2]
    rots_sum[2] += rots[2]

trans_avg = [trans_sum[0]/count, trans_sum[1]/count, trans_sum[2]/count]
rots_avg = [rots_sum[0]/count, rots_sum[1]/count, rots_sum[2]/count]

cmds.xform(master_helper, ws=True, translation=trans_avg, rotation=rots_avg)
cmds.move(center[0], center[1], center[2], master_helper)

cmds.setKeyframe(master_helper)
  1. I am wondering if it will also be possible to modify the master controller shape (the bounding box) where it will be located at the center of the child controllers?

Open to any suggestions but my main feature is to have the master controller to move together with the selections + if it rotates/ translates, it should affects the children controllers

I may be misunderstanding what you’re trying to do here, but there’s an inescapable logical problem if you want the master controller to both move the children and be moved by them. Unfortunately it’s like the difference IK vs FK control: somebody must be unambiguously in charge.

You can sidestep the issue with a tool that resets the position of the master to match updated positions of the children. That would be the rough equivalent of turning IK off, making some FK adjustments, matching the target and then turning the IK back on.

Or did I misread your issue?