Last active
May 4, 2020 23:13
-
-
Save Onefabis/40686d1c84109d63b2d2c18d7c3d692f to your computer and use it in GitHub Desktop.
Transform multiple controllers at once
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
''' | |
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