CBdeleteConnection in python

Hey all,

So i am making a mirror pose tool in Maya, i was able to get most of the way there taking some empty group nodes and mirroring them along an axis, then deleting a point and orient constaint. However i just started to notice that when an object is keyed the keyed value overwrites the point constraint values right after they are deleted.

So what i am going to do is break the connection on the channel currently being constrained and just rekey it after the constraint is deleted.

Now that you know what i am doing, the CBdeleteConnection command in mel doesnt appear to be in python, so i am trying to figure out a way to do this by either running a mel command through python (which i cant seem to find out how to do) or if there is another way that i may be missing that you guys may have an idea about.

Thanks :slight_smile:

You can try this:

import maya.mel

attr = "object.attribute" #or whatever your attr is
maya.mel.eval("source channelBoxCommand; CBdeleteConnection \"%s\""%attr)

This is a pretty brute force way to do it, if you’re sticking in python there are definitely some more elegant solutions. Can you describe your flow in a bit more detail?

I just found pmg.disconnectAttr(), however it disconnects all outputs as well if i dont pass a destination, which could cause problems later

looks like this will do what i want

Here is my group creation snippet:

                keyArray = createKeyArr(obj, -1, ['.r'], ['x','y'])
                
                grpNode = pmg.createNode('transform' , n='TempMirrorGrp')
                snap(mirPlane , grpNode, True,True )
                posCtrl = pmg.createNode('transform', n = 'tempMirrorObj')
                snap(str(obj),posCtrl, True,True)
                pmg.parent(posCtrl, grpNode)
                    #snap new node to the control to be mirrored
                pmg.setAttr(grpNode.sz , -1)
                    #Assign orientation by placing keys directly
                assignKeys(mirObject, keyArray, refFile)
                    #snap control to the position object not orient
                snap(posCtrl, mirObject, True, False)
                pmg.delete(grpNode)

Here is my Snap method:

i moved to an xform method for the position that seemed to get me the best results with already keyed controls

 

def snap(master , slave, pos , orient):
    points = ['x','y','z']
    if pos:
        position = pmg.xform(master, q=True, t=True, ws=True)
        pmg.xform(slave, t=position, ws=True, a=True)
        
        #for axis in points:
        #    if pmg.getAttr(str(slave) +'.t' + axis, k=True):
        #        printOut('Snapping Translation %s' % axis ) 
        #        string = (''.join(points)).replace(axis, '')
        #        pmg.delete(pma.pointConstraint(master, slave, mo=False, sk=list(string)[0],sk=list(string)[1] ))
    if orient:
        for axis in points:
            if pmg.getAttr(str(slave) +'.r' + axis, k=True):
                printOut('Snapping Rotation %s %s %s' % (axis ,master ,slave)) 
                string = (''.join(points)).replace(axis, '')
                pmg.delete(pma.orientConstraint(master , slave , mo=False,sk=list(string)[0],sk=list(string)[1] ))
        

You can run MEL through python like so:

import maya.mel as mel
mel.eval("CBdeleteConnection;")

The issue is that CBdeleteConnection is lazy loaded, so it’s not always available (You can manually source it though).

But the better way to do it (Which CBdeleteConnection just wraps) is disconnectAttr, which if you know your source and destination already is the way to go.

Here’s a basic re-write of CBdeleteConnection in python (I left out the part where it handles character sets, because I don’t need that section. If you do, then you’ll have to convert that part over as well.

def deleteConnection(plug):
	if cmds.connectionInfo(plug, isDestination=True):
		plug = cmds.connectionInfo(plug, getExactDestination=True)
		readOnly = cmds.ls(plug, ro=True)
		#delete -icn doesn't work if destination attr is readOnly 
		if readOnly:
			source = cmds.connectionInfo(plug, sourceFromDestination=True)
			cmds.disconnectAttr(source, plug)
		else:
			cmds.delete(plug, icn=True)

Edit - Well, Seth already answered your first question. Meh, leaving this in case it helps.

Thanks guys!

Temujin that seems to be a bit cleaner, i would prefer to stick inside python, you just saved me a hour or so of traversing source code :slight_smile:

Another option could be to log your attributes as you perform the snaps and constraints then call Attribute.disconnect() for each one when you’re finished, since it seems like you’d know based on the specific mirroring options what you need to manage.

[QUOTE=raven5326;7776]Thanks guys!

Temujin that seems to be a bit cleaner, i would prefer to stick inside python, you just saved me a hour or so of traversing source code :-)[/QUOTE]

Just an FYI:

whatIs "CbdeleteConnection";

in mel will give you the exact file that it (Or any other function) is defined in.

hmm… disconnectAttr will remove all the keyframes… that is bad… maybe i can just set the keyframe with stored values…

Have you looked into bakeResults?

def bakeAnimation(controls, start, end):
	cmds.bakeResults(controls,
			simulation = True,
			t=(start, end),
			sampleBy = 1,
			disableImplicitControl = True,
			sparseAnimCurveBake = False,
			controlPoints = False, 
			shape=True,
			at=['tx', 'ty', 'tz', 'rx', 'ry', 'rz', 'sx', 'sy', 'sz'])

You could constrain your controls to the mirror object, bake that frame, and then just delete the constraints off.

that certainly could work, however i have to put a range of times in, if i could just do one from that would be better, otherwise it could overwrite keys

edit: documentation says i can but it wont seem to let me pass a single value in

cmds.bakeResults(str(slave), simulation = True, t=(6,7), iub=False ,sampleBy = 1,disableImplicitControl = True,sparseAnimCurveBake = False,
                controlPoints = False, shape=True,at=['r'+ axis])

had to put in iub (includeUpperBounds)

this certainly gets me closer!

edit: Its working! thanks guys

I think for the time requirement it requires a tuple, but not two values (Assuming you use the iub flag). You can make a single value tuple by leaving a trailing comma after your start frame:

t=(6,)

since t=(6) is just 6, but t=(6,) is the same as doing t=tuple(6)