def resetSkinCluster( skinCluster ): ''' splats the current pose of the skeleton into the skinCluster - ie whatever the current pose is becomes the bindpose ''' skinInputMatrices = listConnections( '%s.matrix' % skinCluster, plugs=True, connections=True, destination=False ) #this happens if the skinCluster is bogus - its possible for deformers to become orphaned in the scene if skinInputMatrices is None: return #get a list of dag pose nodes connected to the skin cluster dagPoseNodes = listConnections( skinCluster, d=False, type='dagPose' ) or [] iterInputMatrices = iter( skinInputMatrices ) for dest in iterInputMatrices: src = iterInputMatrices.next() srcNode = src.split( '.' )[ 0 ] idx = dest[ dest.rfind( '[' )+1:-1 ] matrixAsStr = ' '.join( map( str, cmd.getAttr( '%s.worldInverseMatrix' % srcNode ) ) ) melStr = 'setAttr -type "matrix" %s.bindPreMatrix[%s] %s' % (skinCluster, idx, matrixAsStr) mel.eval( melStr ) #reset the stored pose in any dagposes that are conn for dPose in dagPoseNodes: dagPose( srcNode, reset=True, n=dPose )
def buildControl(name, placementDesc=DEFAULT_PLACE_DESC, pivotModeDesc=PivotModeDesc.MID, shapeDesc=DEFAULT_SHAPE_DESC, colour=DEFAULT_COLOUR, constrain=True, oriented=True, offset=Vector((0, 0, 0)), offsetSpace=SPACE_OBJECT, size=Vector((1, 1, 1)), scale=1.0, autoScale=False, parent=None, qss=None, asJoint=False, freeze=True, lockAttrs=('scale', ), hideAttrs=DEFAULT_HIDE_ATTRS, niceName=None, displayLayer=None): ''' this rather verbosely called function deals with creating control objects in a variety of ways. the following args take "struct" like instances of the classes defined above, so look to them for more detail on defining those options displayLayer (int) will create layers (if doesn't exist) and add control shape to that layer. layer None or zero doesn't create. ''' select(cl=True) #sanity checks... if not isinstance(placementDesc, PlaceDesc): if isinstance(placementDesc, (list, tuple)): placementDesc = PlaceDesc(*placementDesc) else: placementDesc = PlaceDesc(placementDesc) if not isinstance(shapeDesc, ShapeDesc): if isinstance(shapeDesc, (list, tuple)): shapeDesc = ShapeDesc(*shapeDesc) else: shapeDesc = ShapeDesc(shapeDesc) offset = Vector(offset) #if we've been given a parent, cast it to be an MObject so that if its name path changes (for example if #parent='aNode' and we create a control called 'aNode' then the parent's name path will change to '|aNode' - yay!) if parent: parent = asMObject(parent) #unpack placement objects place, align, pivot = placementDesc.place, placementDesc.align, placementDesc.pivot if shapeDesc.surfaceType == ShapeDesc.SKIN: shapeDesc.curveType = ShapeDesc.NULL_SHAPE #never build curve shapes if the surface type is skin if shapeDesc.joints is None: shapeDesc.joints = [str(place)] shapeDesc.expand *= scale #determine auto scale/size - if nessecary if autoScale: _scale = list(getJointSize([place] + (shapeDesc.joints or []))) _scale = sorted(_scale)[-1] if abs(_scale) < 1e-2: print 'AUTO SCALE FAILED', _scale, name, place _scale = scale scale = _scale if size is AUTO_SIZE: tmpKw = {} if oriented else {'space': SPACE_WORLD} size = getJointSize([place] + (shapeDesc.joints or []), **tmpKw) for n, v in enumerate(size): if abs(v) < 1e-2: size[n] = scale scale = 1.0 #if we're doing a SKIN shape, ensure there is actually geometry skinned to the joints, otherwise bail on the skin and change to the default type if shapeDesc.surfaceType == ShapeDesc.SKIN: try: #loop over all joints and see if there is geo skinned to it for j in shapeDesc.joints: verts = meshUtils.jointVerts( j, tolerance=DEFAULT_SKIN_EXTRACTION_TOLERANCE) #if so throw a breakException to bail out of the loop if verts: raise BreakException #if we get this far that means none of the joints have geo skinned to them - so set the surface and curve types to their default values shapeDesc.surfaceType = shapeDesc.curveType = ShapeDesc.DEFAULT_TYPE print 'WARNING - surface type was set to SKIN, but no geometry is skinned to the joints: %s' % shapeDesc.joints except BreakException: pass #build the curve shapes first if shapeDesc.curveType != ShapeDesc.NULL_SHAPE \ and shapeDesc.curveType != ShapeDesc.SKIN: curveShapeFile = getFileForShapeName(shapeDesc.curveType) assert curveShapeFile is not None, "cannot find shape %s" % shapeDesc.curveType createCmd = ''.join(curveShapeFile.read()) mel.eval(createCmd) else: select(group(em=True)) sel = ls(sl=True) obj = asMObject(sel[0]) #now to deal with the surface - if its different from the curve, then build it if shapeDesc.surfaceType != shapeDesc.curveType \ and shapeDesc.surfaceType != ShapeDesc.NULL_SHAPE \ and shapeDesc.surfaceType != ShapeDesc.SKIN: #if the typesurface is different from the typecurve, then first delete all existing surface shapes under the control shapesTemp = listRelatives(obj, s=True, pa=True) for s in shapesTemp: if nodeType(s) == "nurbsSurface": delete(s) #now build the temporary control surfaceShapeFile = getFileForShapeName(shapeDesc.surfaceType) assert surfaceShapeFile is not None, "cannot find shape %s" % shapeDesc.surfaceType createCmd = ''.join(surfaceShapeFile.read()) mel.eval(createCmd) #and parent its surface shape nodes to the actual control, and then delete it tempSel = ls(sl=True) shapesTemp = listRelatives(tempSel[0], s=True, pa=True) or [] for s in shapesTemp: if nodeType(s) == "nurbsSurface": cmd.parent(s, obj, add=True, s=True) delete(tempSel[0]) select(sel) #if the joint flag is true, parent the object shapes under a joint instead of a transform node if asJoint: select(cl=True) j = joint() for s in listRelatives(obj, s=True, pa=True) or []: cmd.parent(s, j, add=True, s=True) setAttr('%s.radius' % j, keyable=False) setAttr('%s.radius' % j, cb=False) delete(obj) obj = asMObject(j) setAttr('%s.s' % obj, scale, scale, scale) #rename the object - if no name has been given, call it "control". if there is a node with the name already, get maya to uniquify it if not name: name = 'control' if objExists(name): name = '%s#' % name rename(obj, name) #move the pivot - if needed makeIdentity(obj, a=1, s=1) shapeStrs = getShapeStrs(obj) if pivotModeDesc == PivotModeDesc.TOP: for s in shapeStrs: move(0, -scale / 2.0, 0, s, r=True) elif pivotModeDesc == PivotModeDesc.BASE: for s in shapeStrs: move(0, scale / 2.0, 0, s, r=True) #rotate it accordingly rot = AXIS_ROTATIONS[shapeDesc.axis] rotate(rot[0], rot[1], rot[2], obj, os=True) makeIdentity(obj, a=1, r=1) #if the user wants the control oriented, create the orientation group and parent the control grp = obj if oriented: grp = group(em=True, n="%s_space#" % obj) cmd.parent(obj, grp) attrState(grp, ['s', 'v'], *LOCK_HIDE) if align is not None: delete(parentConstraint(align, grp)) #place and align if place: delete(pointConstraint(place, grp)) if align: delete(orientConstraint(align, grp)) else: rotate(0, 0, 0, grp, a=True, ws=True) #do the size scaling... if shapeDesc.surfaceType != ShapeDesc.SKIN: for s in getShapeStrs(obj): cmd.scale(size[0], size[1], size[2], s) #if the parent exists - parent the new control to the given parent if parent is not None: grp = cmd.parent(grp, parent)[0] #do offset for s in getShapeStrs(obj): mkw = {'r': True} if offsetSpace == SPACE_OBJECT: mkw['os'] = True elif offsetSpace == SPACE_LOCAL: mkw['ls'] = True elif offsetSpace == SPACE_WORLD: mkw['ws'] = True if offset: move(offset[0], offset[1], offset[2], s, **mkw) if freeze: makeIdentity(obj, a=1, r=1) makeIdentity(obj, a=1, t=1) #always freeze translations #delete shape data that we don't want if shapeDesc.curveType is None: for s in listRelatives(obj, s=True, pa=True) or []: if nodeType(s) == "nurbsCurve": delete(s) if shapeDesc.surfaceType is None: for s in listRelatives(obj, s=True, pa=True) or []: if nodeType(s) == "nurbsSurface": delete(s) #now snap the pivot to alignpivot object if it exists if pivot is not None and objExists(pivot): p = placementDesc.pivotPos move(p[0], p[1], p[2], '%s.rp' % obj, '%s.sp' % obj, a=True, ws=True, rpr=True) #constrain the target object to this control? if constrain: #check to see if the transform is constrained already - if so, bail. buildControl doesn't do multi constraints if not listConnections(pivot, d=0, type='constraint'): if place: parentConstraint(obj, pivot, mo=True) setItemRigControl(pivot, obj) #if the user has specified skin geometry as the representation type, then build the geo #NOTE: this really needs to happen after ALL the placement has happened otherwise the extracted #will be offset from the surface its supposed to be representing if shapeDesc.surfaceType == ShapeDesc.SKIN: #extract the surface geometry geo = meshUtils.extractMeshForJoints(shapeDesc.joints, expand=shapeDesc.expand) #if the geo is None, use the default control representation instead writeTrigger = True if geo is None: writeTrigger = False curveShapeFile = getFileForShapeName(ShapeDesc.DEFAULT_TYPE) createCmd = ''.join(curveShapeFile.read()) mel.eval(createCmd) geo = ls(sl=True)[0] geo = cmd.parent(geo, obj)[0] makeIdentity(geo, a=True, s=True, r=True, t=True) cmd.parent(listRelatives(geo, s=True, pa=True), obj, add=True, s=True) delete(geo) #when selected, turn the mesh display off, and only highlight edges if writeTrigger: triggered.Trigger.CreateTrigger( str(obj), cmdStr= "for( $s in `listRelatives -s -pa #` ) setAttr ( $s +\".displayEdges\" ) 2;" ) #build a shader for the control if colour is not None: colours.setObjShader(obj, colours.getShader(colour, True)) #add to a selection set if desired if qss is not None: sets(obj, add=qss) #hide and lock attributes attrState(obj, lockAttrs, lock=True) attrState(obj, hideAttrs, show=False) if niceName: setNiceName(obj, niceName) # display layer if displayLayer and not int(displayLayer) <= 0: layerName = 'ctrl_%d' % int(displayLayer) allLayers = ls(type='displayLayer') layer = '' if layerName in allLayers: layer = layerName else: layer = createDisplayLayer(n=layerName, number=1, empty=True) setAttr('%s.color' % layer, 24 + int(displayLayer)) for s in listRelatives(obj, s=True, pa=True) or []: connectAttr('%s.drawInfo.visibility' % layer, '%s.v' % s) connectAttr('%s.drawInfo.displayType' % layer, '%s.overrideDisplayType' % s) return obj
def executePostTraceCmd( node ): cmdStr = getPostTraceCmd( node ) resolvedCmdStr = resolveCmdStr( cmdStr, node, [] ) mel.eval( resolvedCmdStr )
def buildControl( name, placementDesc=DEFAULT_PLACE_DESC, pivotModeDesc=PivotModeDesc.MID, shapeDesc=DEFAULT_SHAPE_DESC, colour=DEFAULT_COLOUR, constrain=True, oriented=True, offset=Vector( (0, 0, 0) ), offsetSpace=SPACE_OBJECT, size=Vector( (1, 1, 1) ), scale=1.0, autoScale=False, parent=None, qss=None, asJoint=False, freeze=True, lockAttrs=( 'scale', ), hideAttrs=DEFAULT_HIDE_ATTRS, niceName=None, displayLayer=None ): ''' this rather verbosely called function deals with creating control objects in a variety of ways. the following args take "struct" like instances of the classes defined above, so look to them for more detail on defining those options displayLayer (int) will create layers (if doesn't exist) and add control shape to that layer. layer None or zero doesn't create. ''' select( cl=True ) #sanity checks... if not isinstance( placementDesc, PlaceDesc ): if isinstance( placementDesc, (list, tuple) ): placementDesc = PlaceDesc( *placementDesc ) else: placementDesc = PlaceDesc( placementDesc ) if not isinstance( shapeDesc, ShapeDesc ): if isinstance( shapeDesc, (list, tuple) ): shapeDesc = ShapeDesc( *shapeDesc ) else: shapeDesc = ShapeDesc( shapeDesc ) offset = Vector( offset ) #if we've been given a parent, cast it to be an MObject so that if its name path changes (for example if #parent='aNode' and we create a control called 'aNode' then the parent's name path will change to '|aNode' - yay!) if parent: parent = asMObject( parent ) #unpack placement objects place, align, pivot = placementDesc.place, placementDesc.align, placementDesc.pivot if shapeDesc.surfaceType == ShapeDesc.SKIN: shapeDesc.curveType = ShapeDesc.NULL_SHAPE #never build curve shapes if the surface type is skin if shapeDesc.joints is None: shapeDesc.joints = [ str( place ) ] shapeDesc.expand *= scale #determine auto scale/size - if nessecary if autoScale: _scale = list( getJointSize( [ place ] + (shapeDesc.joints or []) ) ) _scale = sorted( _scale )[ -1 ] if abs( _scale ) < 1e-2: print 'AUTO SCALE FAILED', _scale, name, place _scale = scale scale = _scale if size is AUTO_SIZE: tmpKw = {} if oriented else { 'space': SPACE_WORLD } size = getJointSize( [ place ] + (shapeDesc.joints or []), **tmpKw ) for n, v in enumerate( size ): if abs( v ) < 1e-2: size[ n ] = scale scale = 1.0 #if we're doing a SKIN shape, ensure there is actually geometry skinned to the joints, otherwise bail on the skin and change to the default type if shapeDesc.surfaceType == ShapeDesc.SKIN: try: #loop over all joints and see if there is geo skinned to it for j in shapeDesc.joints: verts = meshUtils.jointVerts( j, tolerance=DEFAULT_SKIN_EXTRACTION_TOLERANCE ) #if so throw a breakException to bail out of the loop if verts: raise BreakException #if we get this far that means none of the joints have geo skinned to them - so set the surface and curve types to their default values shapeDesc.surfaceType = shapeDesc.curveType = ShapeDesc.DEFAULT_TYPE print 'WARNING - surface type was set to SKIN, but no geometry is skinned to the joints: %s' % shapeDesc.joints except BreakException: pass #build the curve shapes first if shapeDesc.curveType != ShapeDesc.NULL_SHAPE \ and shapeDesc.curveType != ShapeDesc.SKIN: curveShapeFile = getFileForShapeName( shapeDesc.curveType ) assert curveShapeFile is not None, "cannot find shape %s" % shapeDesc.curveType createCmd = ''.join( curveShapeFile.read() ) mel.eval( createCmd ) else: select( group( em=True ) ) sel = ls( sl=True ) obj = asMObject( sel[ 0 ] ) #now to deal with the surface - if its different from the curve, then build it if shapeDesc.surfaceType != shapeDesc.curveType \ and shapeDesc.surfaceType != ShapeDesc.NULL_SHAPE \ and shapeDesc.surfaceType != ShapeDesc.SKIN: #if the typesurface is different from the typecurve, then first delete all existing surface shapes under the control shapesTemp = listRelatives( obj, s=True, pa=True ) for s in shapesTemp: if nodeType( s ) == "nurbsSurface": delete( s ) #now build the temporary control surfaceShapeFile = getFileForShapeName( shapeDesc.surfaceType ) assert surfaceShapeFile is not None, "cannot find shape %s" % shapeDesc.surfaceType createCmd = ''.join( surfaceShapeFile.read() ) mel.eval( createCmd ) #and parent its surface shape nodes to the actual control, and then delete it tempSel = ls( sl=True ) shapesTemp = listRelatives( tempSel[0], s=True, pa=True ) or [] for s in shapesTemp: if nodeType(s) == "nurbsSurface": cmd.parent( s, obj, add=True, s=True ) delete( tempSel[ 0 ] ) select( sel ) #if the joint flag is true, parent the object shapes under a joint instead of a transform node if asJoint: select( cl=True ) j = joint() for s in listRelatives( obj, s=True, pa=True ) or []: cmd.parent( s, j, add=True, s=True ) setAttr( '%s.radius' % j, keyable=False ) setAttr( '%s.radius' % j, cb=False ) delete( obj ) obj = asMObject( j ) setAttr( '%s.s' % obj, scale, scale, scale ) #rename the object - if no name has been given, call it "control". if there is a node with the name already, get maya to uniquify it if not name: name = 'control' if objExists( name ): name = '%s#' % name rename( obj, name ) #move the pivot - if needed makeIdentity( obj, a=1, s=1 ) shapeStrs = getShapeStrs( obj ) if pivotModeDesc == PivotModeDesc.TOP: for s in shapeStrs: move( 0, -scale/2.0, 0, s, r=True ) elif pivotModeDesc == PivotModeDesc.BASE: for s in shapeStrs: move( 0, scale/2.0, 0, s, r=True ) #rotate it accordingly rot = AXIS_ROTATIONS[ shapeDesc.axis ] rotate( rot[0], rot[1], rot[2], obj, os=True ) makeIdentity( obj, a=1, r=1 ) #if the user wants the control oriented, create the orientation group and parent the control grp = obj if oriented: grp = group( em=True, n="%s_space#" % obj ) cmd.parent( obj, grp ) attrState( grp, ['s', 'v'], *LOCK_HIDE ) if align is not None: delete( parentConstraint( align, grp ) ) #place and align if place: delete( pointConstraint( place, grp ) ) if align: delete( orientConstraint( align, grp ) ) else: rotate( 0, 0, 0, grp, a=True, ws=True ) #do the size scaling... if shapeDesc.surfaceType != ShapeDesc.SKIN: for s in getShapeStrs( obj ): cmd.scale( size[0], size[1], size[2], s ) #if the parent exists - parent the new control to the given parent if parent is not None: grp = cmd.parent( grp, parent )[0] #do offset for s in getShapeStrs( obj ): mkw = { 'r': True } if offsetSpace == SPACE_OBJECT: mkw[ 'os' ] = True elif offsetSpace == SPACE_LOCAL: mkw[ 'ls' ] = True elif offsetSpace == SPACE_WORLD: mkw[ 'ws' ] = True if offset: move( offset[0], offset[1], offset[2], s, **mkw ) if freeze: makeIdentity( obj, a=1, r=1 ) makeIdentity( obj, a=1, t=1 ) #always freeze translations #delete shape data that we don't want if shapeDesc.curveType is None: for s in listRelatives( obj, s=True, pa=True ) or []: if nodeType(s) == "nurbsCurve": delete(s) if shapeDesc.surfaceType is None: for s in listRelatives( obj, s=True, pa=True ) or []: if nodeType(s) == "nurbsSurface": delete(s) #now snap the pivot to alignpivot object if it exists if pivot is not None and objExists( pivot ): p = placementDesc.pivotPos move( p[0], p[1], p[2], '%s.rp' % obj, '%s.sp' % obj, a=True, ws=True, rpr=True ) #constrain the target object to this control? if constrain: #check to see if the transform is constrained already - if so, bail. buildControl doesn't do multi constraints if not listConnections( pivot, d=0, type='constraint' ): if place: parentConstraint( obj, pivot, mo=True ) setItemRigControl( pivot, obj ) #if the user has specified skin geometry as the representation type, then build the geo #NOTE: this really needs to happen after ALL the placement has happened otherwise the extracted #will be offset from the surface its supposed to be representing if shapeDesc.surfaceType == ShapeDesc.SKIN: #extract the surface geometry geo = meshUtils.extractMeshForJoints( shapeDesc.joints, expand=shapeDesc.expand ) #if the geo is None, use the default control representation instead writeTrigger = True if geo is None: writeTrigger = False curveShapeFile = getFileForShapeName( ShapeDesc.DEFAULT_TYPE ) createCmd = ''.join( curveShapeFile.read() ) mel.eval( createCmd ) geo = ls( sl=True )[ 0 ] geo = cmd.parent( geo, obj )[0] makeIdentity( geo, a=True, s=True, r=True, t=True ) cmd.parent( listRelatives( geo, s=True, pa=True ), obj, add=True, s=True ) delete( geo ) #when selected, turn the mesh display off, and only highlight edges if writeTrigger: triggered.Trigger.CreateTrigger( str( obj ), cmdStr="for( $s in `listRelatives -s -pa #` ) setAttr ( $s +\".displayEdges\" ) 2;" ) #build a shader for the control if colour is not None: colours.setObjShader( obj, colours.getShader( colour, True ) ) #add to a selection set if desired if qss is not None: sets( obj, add=qss ) #hide and lock attributes attrState( obj, lockAttrs, lock=True ) attrState( obj, hideAttrs, show=False ) if niceName: setNiceName( obj, niceName ) # display layer if displayLayer and not int( displayLayer ) <= 0 : layerName = 'ctrl_%d' % int( displayLayer ) allLayers = ls( type='displayLayer' ) layer = '' if layerName in allLayers: layer = layerName else: layer = createDisplayLayer( n=layerName, number=1, empty=True ) setAttr( '%s.color' % layer, 24 + int( displayLayer ) ) for s in listRelatives( obj, s=True, pa=True ) or []: connectAttr( '%s.drawInfo.visibility' % layer, '%s.v' % s ) connectAttr( '%s.drawInfo.displayType' % layer, '%s.overrideDisplayType' % s ) return obj