Skip to content

Instantly share code, notes, and snippets.

@Onefabis
Last active May 4, 2020 23:13
Show Gist options
  • Save Onefabis/40686d1c84109d63b2d2c18d7c3d692f to your computer and use it in GitHub Desktop.
Save Onefabis/40686d1c84109d63b2d2c18d7c3d692f to your computer and use it in GitHub Desktop.
Transform multiple controllers at once
'''
Save the file to Maya script folder and then just
run this three-line code in script editor to call the UI
import maya.cmds as mc
import containerAnim
containerAnim.containerAnim().UI()
'''
import maya.cmds as mc
class containerAnim( object ):
winName = "group_transform"
def __init__( self ):
self.scrJob = -1
self.scrAnimJob = -1
self.scrUpdateJob = -1
self.scrUIJob = -1
self.cube = ''
self.sel = []
self.lock = 2
self.worldRotPivot = []
self.worldScPivot = []
self.currentT = None
# Create UI
def UI( self ):
if mc.window( self.winName, ex=1 ):
mc.deleteUI( self.winName )
self.win = mc.window( self.winName, cc=self.deleteMoveJob, tlb=1, t="Group transform" )
self.frame = mc.formLayout( p=self.win )
self.mainButton = mc.button( l="Start", bgc=(0.25,0.5,0), c=lambda *x:self.changeButtonState(), p=self.frame )
self.refTF = mc.textField( h=25, cc=lambda *x: self.changeCubePivot() )
mc.popupMenu( p=self.refTF )
mc.menuItem( l='Save pivot', c=lambda *x: self.updatePivot( 'save' ) )
mc.menuItem( l='Delete pivot', c=lambda *x: self.updatePivot( 'delete' ) )
self.pickButton = mc.button( l="Pick", h=23, c=lambda *x:self.changeRefTF(), p=self.frame )
mc.formLayout( self.frame, e=1, af=( self.mainButton, 'top', 2 ) )
mc.formLayout( self.frame, e=1, af=( self.mainButton, 'left', 2 ) )
mc.formLayout( self.frame, e=1, ac=( self.mainButton, 'bottom', 3, self.pickButton ) )
mc.formLayout( self.frame, e=1, af=( self.mainButton, 'right', 2 ) )
mc.formLayout( self.frame, e=1, af=( self.refTF, 'left', 1 ) )
mc.formLayout( self.frame, e=1, ac=( self.refTF, 'right', 2, self.pickButton ) )
mc.formLayout( self.frame, e=1, af=( self.refTF, 'bottom', 3 ) )
mc.formLayout( self.frame, e=1, af=( self.pickButton, 'bottom', 4 ) )
mc.formLayout( self.frame, e=1, af=( self.pickButton, 'right', 2 ) )
mc.showWindow()
mc.window( self.win, e=1, w=120, h=66 )
# Move child objects accordingly to the container
def transformObj( self ):
try:
mc.undoInfo( ock =1 )
# If reference pivot object exist check counter, if counter = 2 mean that frame is still and we can move the childs
if self.lock == 2:
for s in xrange( len( self.sel ) ):
mc.matchTransform( self.sel[s], self.childPoints[s] )
# Contibue to reset counter in case of fast frame switching
if self.lock == 1:
self.lock = 2
finally:
mc.undoInfo( cck =1 )
# Edit conrainer object
def initGrpSelection( self ):
if self.currentT != mc.currentTime( q=1 ):
bbox = mc.exactWorldBoundingBox( self.sel, ii=1 )
center = [ sum(k)/2.0 for k in [ bbox[0::3], bbox[1::3], bbox[2::3] ] ]
dims = [ k[1] - k[0] for k in [ bbox[0::3], bbox[1::3], bbox[2::3] ] ]
cubenode = mc.listHistory( self.cube[0], pdo=1, il=0 )[0]
mc.setAttr( cubenode + '.width', dims[0] )
mc.setAttr( cubenode + '.height', dims[1] )
mc.setAttr( cubenode + '.depth', dims[2] )
mc.xform( self.grp, ws=1, t=center, p=1 )
mc.makeIdentity( self.cube[0], apply=False, t=1, r=1, s=1 )
self.changeCubePivot()
mc.xform( self.cube[0], ws=1, t=center, p=1 )
if self.worldRotPivot and self.worldScPivot:
mc.xform( self.cube[0], ws=1, rp=self.worldRotPivot )
mc.xform( self.cube[0], ws=1, sp=self.worldScPivot )
# If reference pivot object exist add counter to protect autokey while fast frame switch
refNode = mc.textField( self.refTF, q=1, tx=1 )
if ( self.worldRotPivot and self.worldScPivot ) or ( refNode and mc.objExists( refNode ) ):
if self.lock == 2:
self.lock = 1
else:
self.lock = 2
self.currentT = mc.currentTime(q=1)
def updatePivot( self, state ):
if state == 'save':
if self.cube:
self.worldRotPivot = mc.xform( self.cube[0], ws=1, q=1, rp=1 )
self.worldScPivot = mc.xform( self.cube[0], ws=1, q=1, sp=1 )
elif state == 'delete':
self.worldRotPivot = []
self.worldScPivot = []
if self.cube:
mc.xform( self.cube[0], cpc=1 )
def changeCubePivot( self ):
if mc.button( self.mainButton, q=1, l=1) == 'Stop':
refNode = mc.textField( self.refTF, q=1, tx=1 )
if refNode and mc.objExists( refNode ):
mc.xform( self.cube[0], ws=1, rp=mc.xform( refNode, q=1, ws=1, rp=1 ), p=1 )
mc.xform( self.cube[0], ws=1, sp=mc.xform( refNode, q=1, ws=1, sp=1 ), p=1 )
else:
bbox = mc.exactWorldBoundingBox( self.sel, ii=1 )
center = [ sum(k)/2.0 for k in [ bbox[0::3], bbox[1::3], bbox[2::3] ] ]
mc.xform( self.cube[0], ws=1, rp=center, p=1 )
mc.xform( self.cube[0], ws=1, sp=center, p=1 )
# Scriptjob when container moved
def startMoveJob( self ):
self.cubePos = mc.xform( self.cube[0], ws=1, a=1, q=1, t=1 )
self.cubeRot = mc.xform( self.cube[0], ws=1, a=1, q=1, ro=1 )
mc.select( self.cube[0], r=1 )
self.scrJob = mc.scriptJob( attributeChange=[ self.cube[0] + '.xformMatrix', self.transformObj ], cu=1, kws=1 )
# Scriptjob when current frame changed
def startAnimJob( self ):
try:
self.initGrpSelection()
except: pass
for s in xrange( len( self.sel ) ):
mc.matchTransform( self.childPoints[s], self.sel[s] )
# Switch main button state
def changeButtonState( self ):
if mc.button( self.mainButton, q=1, l=1) == 'Start':
self.start()
if mc.ls( sl=1 ):
mc.button( self.mainButton, e=1, l='Stop', bgc=(0.5,0,0.25) )
else:
self.deleteMoveJob()
mc.button( self.mainButton, e=1, l='Start', bgc=(0.25,0.5,0) )
# Stop all scriptjobs
def deleteMoveJob( self ):
if mc.scriptJob ( ex = self.scrAnimJob ):
mc.scriptJob ( k = self.scrAnimJob )
mc.delete( 'groupMoveContainer' )
mc.select( self.sel, r=1 )
if mc.scriptJob( ex = self.scrJob ):
mc.scriptJob( k = self.scrJob )
if mc.scriptJob( ex = self.scrUpdateJob ):
mc.scriptJob ( k = self.scrUpdateJob )
self.currentT = None
# Start all scrip jobs
def start( self ):
self.sel = mc.ls( sl=1 )
self.childPoints = []
if len( self.sel ) > 0:
# Create container object
self.cube = mc.polyCube( n='cubeMoveContainer' )
mc.setAttr( self.cube[0] + '.overrideEnabled', 1 )
mc.setAttr( self.cube[0] + '.overrideShading', 0 )
self.grp = mc.group( em=1, n='groupMoveContainer' )
mc.evalDeferred( "mc.parent( '%s', '%s' )" %( self.cube[0], self.grp ) )
mc.evalDeferred( self.startAnimJob )
for s in xrange( len( self.sel ) ):
loc = mc.group( em=1, n=self.sel[s] + '_Grouploc' )
mc.evalDeferred( "mc.parent( '%s', '%s' )" %( loc, self.cube[0] ) )
self.childPoints.append(loc)
mc.evalDeferred( self.startMoveJob )
self.scrAnimJob = mc.scriptJob( tc=( self.startAnimJob ), cu=1, kws=1 )
self.scrUpdateJob = mc.scriptJob( e=[ 'SelectionChanged', self.updateChildPoints ], cu=1, kws=1 )
self.scrUIJob = mc.scriptJob( e=[ 'PostSceneRead', self.updateUI ] )
else:
mc.warning( 'Select at least one object' )
def updateUI( self ):
if not mc.scriptJob ( ex = self.scrAnimJob ):
mc.button( self.mainButton, e=1, l='Start', bgc=(0.25,0.5,0) )
mc.textField( self.refTF, e=1, tx='' )
def updateChildPoints( self ):
if len( mc.ls( sl=True ) ) == 1 and mc.ls( sl=True )[0] == self.cube[0]:
for s in xrange( len( self.sel ) ):
mc.matchTransform( self.childPoints[s], self.sel[s] )
refNode = mc.textField( self.refTF, q=1, tx=1 )
if refNode and mc.objExists( refNode ):
mc.xform( self.cube[0], ws=1, rp=mc.xform( refNode, q=1, ws=1, rp=1 ), p=1 )
mc.xform( self.cube[0], ws=1, sp=mc.xform( refNode, q=1, ws=1, sp=1 ), p=1 )
# Cahnge reference pivot object by 'Pick' button
def changeRefTF( self ):
sel = mc.ls( sl=1, l=1 )
if sel:
mc.textField( self.refTF, e=1, tx=sel[0] )
self.changeCubePivot()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment