import maya.cmds as mc from functools import partial #check if UI is already open if mc.window('spaceMatchUI', query=True, exists=True): mc.deleteUI('spaceMatchUI', window=True) def warningMsg(msg, arg=None): mc.confirmDialog(title='Warning', message=msg, button='ok') #parenting functions objects = None world = None driver1 = None driver2 = None def assignObjects(arg=None): global objects objects = mc.ls(sl=True) if not objects: warningMsg('Please select at least one object') def assignWorld(arg=None): global world world = mc.ls(sl=True) if not world: warningMsg('Please select world') def assignDriver1(arg=None): global driver1 driver1 = mc.ls(sl=True) if not driver1: warningMsg('Please select driver') def assignDriver2(arg=None): global driver2 driver2 = mc.ls(sl=True) if not driver2: warningMsg('Please select driver') def parentObjects(arg=None): #Crates a locator parent for each object. Constraints locators to world/driver1/driver2 and sets set driven key if objects and world and driver1: for obj in objects: #create locator loc = mc.spaceLocator(name=obj+'_loc') #parent constraint to object constraint = mc.parentConstraint( obj, loc ) #break constraint mc.delete(constraint) #parent object to locator mc.parent( obj, loc ) #freeze transforms mc.makeIdentity(apply=True, t=1, r=1, s=1, n=0) #turn locator display off mc.select(loc) loc_shape = mc.listRelatives(s=True) mc.setAttr(loc_shape[0]+'.visibility',0) #create constraints loc_parentConstraint = mc.parentConstraint( world[0], loc, w=1.0, mo=True ) mc.parentConstraint(driver1[0], loc, w=0.0, mo=True ) if driver2: mc.parentConstraint(driver2[0] , loc, w=0.0, mo=True) #add attribute 'follow' mc.select(obj) enumNames = '' if driver2: enumNames = str(world[0])+':'+str(driver1[0])+':'+str(driver2[0]) else: enumNames = str(world[0])+':'+str(driver1[0]) mc.addAttr( ln='follow', at='enum', enumName=enumNames, k=True ) #set set driven keys #world mc.setDrivenKeyframe( loc_parentConstraint[0] + '.' + str(world[0]) + 'W0', cd= obj + '.follow' ) mc.setDrivenKeyframe( loc_parentConstraint[0] + '.' + str(driver1[0]) + 'W1', cd= obj + '.follow' ) if driver2: mc.setDrivenKeyframe( loc_parentConstraint[0] + '.' + str(driver2[0]) + 'W2', cd= obj + '.follow' ) #driver1 mc.setDrivenKeyframe( loc_parentConstraint[0] + '.' + str(world[0]) + 'W0', v=0.0, cd= obj + '.follow', dv=1 ) mc.setDrivenKeyframe( loc_parentConstraint[0] + '.' + str(driver1[0]) + 'W1',v=1.0, cd= obj + '.follow', dv=1 ) if driver2: mc.setDrivenKeyframe( loc_parentConstraint[0] + '.' + str(driver2[0]) + 'W2',v=0.0, cd= obj + '.follow', dv=1 ) #driver2 if driver2: mc.setDrivenKeyframe( loc_parentConstraint[0] + '.' + world[0] + 'W0', v=0.0, cd= obj + '.follow', dv=2 ) mc.setDrivenKeyframe( loc_parentConstraint[0] + '.' + driver1[0] + 'W1',v=0.0, cd= obj + '.follow', dv=2 ) mc.setDrivenKeyframe( loc_parentConstraint[0] + '.' + driver2[0] + 'W2', v=1.0, cd= obj + '.follow', dv=2 ) else: warningMsg('Please select at least one object, one world and one driver') #space matching functions obj = None layoutList = [] driverList = [] driversChannel = 'follow' def clearButtons(arg=None): global layoutList for ly in layoutList: mc.deleteUI(ly) layoutList = [] def assignObj(arg=None): clearButtons() global layoutList global obj global driverList sel = mc.ls(sl=True) if sel: obj = sel[0] mc.text(objSelected, e=True, l=str(obj)) #find drivers driverStr = mc.attributeQuery(str(driversChannel), node= obj, le=True) driverList = driverStr[0].split(':') #add buttons to layout for driver in driverList: mc.setParent( win ) ly = mc.columnLayout(adjustableColumn=True) layoutList.append(ly) mc.button(label=str(driver), command= partial(spaceMatch, driver)) mc.setParent( win ) else: warningMsg('Please select object') def assignChannel(arg=None): global driversChannel driversChannel = mc.textField(chanName, q=True, tx=True) print(driversChannel) def spaceMatch(drv, arg=None): global obj global driverList #get ws tranlation and rotation tValues = mc.xform( obj, ws=True, q=True, t=True) rValues = mc.xform( obj, ws=True, q=True, ro=True) tx,ty,tz = tValues[0],tValues[1],tValues[2] rx,ry,rz = rValues[0],rValues[1],rValues[2] #switch space enumIndex = driverList.index(drv) mc.setAttr(str(obj)+'.'+ str(driversChannel), enumIndex ) #set ws trans and rot mc.xform( obj, a=True, ws=True, t=tValues) mc.xform( obj, a=True, ws=True, ro=rValues) ######## GUI win = mc.window('spaceMatchUI', title='Dynamic parenting & Space Matching') mc.columnLayout( adjustableColumn=True ) #Dynamic parent frame mc.frameLayout( label='DYNAMIC PARENTING', borderStyle='out' ) mc.rowColumnLayout(numberOfColumns=4, columnWidth=[(1, 100), (2, 100), (3, 100), (4, 100)]) mc. button(label='Object(s)', command= partial(assignObjects)) mc. button(label='World', command= partial(assignWorld)) mc. button(label='Driver1', command= partial(assignDriver1)) mc. button(label='Driver2', command= partial(assignDriver2)) mc.setParent( '..' ) mc.setParent( '..' ) mc. button(label='PARENT OBJECTS', command= partial(parentObjects)) #Space switch frame mc.frameLayout( label='SPACE MATCHING', borderStyle='in' ) mc.rowColumnLayout(numberOfColumns=3, columnWidth=[(1, 100), (2, 200), (3, 100)]) mc.text(label='Selected object:', align='left') objSelected = mc.text('select object', font='obliqueLabelFont', align='left') mc. button(label='assign', command= partial(assignObj)) mc.text(label='Channel name:', align='left') chanName = mc.textField(tx='follow') mc. button(label='assign', command= partial(assignChannel)) mc.setParent( '..' ) mc.setParent( '..' ) #Drivers list mc.frameLayout( label='Drivers list', borderStyle='out' ) #Show mc.showWindow('spaceMatchUI')