def createCompoundCurve(inCurves): """ Merges all the controls into one transform node. @param inCurves: List of Strings. Names of curves to combine under one transform node. The first curve in the list is considered the parent of all the others. @return: MObject. Compound curve transform node. """ # List for creating the compound. compoundList = [] # Get the nurbs curves of all curves in the list. for index in range(1, len(inCurves)): curve = NodeUtility.getDagPath(inCurves[index]) for child in xrange(curve.childCount()): nurb = curve.child(child) nurbDagPath = OpenMaya.MDagPath.getAPathTo(nurb) if nurb.apiType() == OpenMaya.MFn.kNurbsCurve: compoundList.append(nurbDagPath.fullPathName()) # Add the transform of the parent curve. This is the first curve passed into # the function. parent = NodeUtility.getDagPath(inCurves[0]) compoundList.append(parent.fullPathName()) # Now parent the shapes to the first curve's transform node. cmds.parent(compoundList, shape=True, relative=True) # Delete the remaining transform nodes of the other curves. for index in range(1, len(inCurves)): cmds.delete(inCurves[index]) # Returns a MObject. return NodeUtility.getDependNode(parent.fullPathName())
def matchTransforms( inType ): ''' @param inType: String. Type of matching to perform. 'tran', 'rot', or 'all' ''' selObjs = cmds.ls( selection=True, dag=False, ap=True ) if len( selObjs ) == 0: cmds.warning( 'No objects are selected. Select two objects and try again' ) elif len( selObjs ) > 2: cmds.warning( 'To many objects are selected. Select only two objects and try again' ) else: # first object is child, second object is target cObj = selObjs[0] tObj = selObjs[1] # do the matching of child to target MFnTrans = OpenMaya.MFnTransform() childDagPath = NodeUtility.getDagPath( cObj ) MFnTrans.setObject( childDagPath ) targetMatrix = getMatrix( tObj, 'worldMatrix' ) if inType == 'tran' or inType == 'all': childTranslation = getMatrixTranslation( targetMatrix, OpenMaya.MSpace.kWorld ) MFnTrans.setTranslation( childTranslation, OpenMaya.MSpace.kWorld ) if inType == 'rot' or inType == 'all': childRotation = getMatrixRotation( targetMatrix, 'quat' ) MFnTrans.setRotation( childRotation, OpenMaya.MSpace.kWorld )
def applyStoredTransforms( sourceObj, targetObj ): ''' Applies stored transform data for a control object. @param sourceObj: String. Name of object to pull data from. @param targetObj: String. Name of object to apply data to. ''' #print 'applyStoredTransforms @@@@@@' #print 'sourceObj: {0}'.format( sourceObj ) #print 'targetObj: {0}'.format( targetObj ) MFnTrans = OpenMaya.MFnTransform() targetDagPath = NodeUtility.getDagPath( targetObj ) MFnTrans.setObject( targetDagPath ) sourcePosPlug = NodeUtility.getPlug( sourceObj, 'controlPosition' ) sourcePosValue = NodeUtility.getPlugValue( sourcePosPlug ) sourcePos = OpenMaya.MVector( sourcePosValue[0], sourcePosValue[1], sourcePosValue[2] ) MFnTrans.setTranslation( sourcePos, OpenMaya.MSpace.kTransform ) sourceRotPlug = NodeUtility.getPlug( sourceObj, 'controlRotation' ) sourceRotValue = NodeUtility.getPlugValue( sourceRotPlug ) sourceRot = OpenMaya.MEulerRotation( sourceRotValue[0], sourceRotValue[1], sourceRotValue[2] ) MFnTrans.setRotation( sourceRot ) sourceSclPlug = NodeUtility.getPlug( sourceObj, 'controlScale' ) sourceSclValue = NodeUtility.getPlugValue( sourceSclPlug ) scaleDoubleArray = OpenMaya.MScriptUtil() scaleDoubleArray.createFromList( [sourceSclValue[0], sourceSclValue[1], sourceSclValue[2]], 3 ) scaleDoubleArrayPtr = scaleDoubleArray.asDoublePtr() MFnTrans.setScale( scaleDoubleArrayPtr )
def getCurveCvs(inCurve): """ Retrieves the positions for all CVs on the curve. @param inCurve: String. Name of the curve from which to retrieve CV positions. @return: List of Dicts. Each dict holds the information for one nurbs curve. since there could be multiple curves for one object we build a list of each curve. """ curDag = NodeUtility.getDagPath(inCurve) curFn = OpenMaya.MFnNurbsCurve() curCvs = OpenMaya.MPointArray() storedCvs = [] childShapes = curDag.childCount() for child in xrange(childShapes): childObj = curDag.child(child) # if childObj.apiType() == OpenMaya.MFn.kNurbsCurve: tempCvs = {} curFn.setObject(childObj) curFn.getCVs(curCvs) for cv in xrange(curCvs.length()): tempCvs[cv] = [curCvs[cv].x, curCvs[cv].y, curCvs[cv].z] storedCvs.append(tempCvs) return storedCvs
def mirrorObject( inSourceObj=None, inTargetObj=None, inMirrorAxis=None ): # Mirrors the position and rotation of one object(source) and applies it to another (target). if inSourceObj is None or inTargetObj is None: # Target object should be selected first, followed by source object. selList = cmds.ls( selection=True, long=True ) if len( selList ) == 2: inTargetObj = selList[0] inSourceObj = selList[1] if inMirrorAxis is None: inMirrorAxis = int( cmds.layoutDialog( ui=mirrorObjectPrompt ) ) if inMirrorAxis is not None: # Get the source module's root world matrix. sourceWorldMatrix = TransformUtility.getMatrix( inSourceObj, 'worldMatrix' ) # Get the source's translation vector. sourceWorldTranslation = TransformUtility.getMatrixTranslation( sourceWorldMatrix, OpenMaya.MFn.kWorld ) # Get the source's rotation matrix. sourceRotationMatrix = OpenMaya.MTransformationMatrix( sourceWorldMatrix ).asRotateMatrix() # Mirror the translation across the selected axis. if inMirrorAxis is 0: sourceWorldTranslation.x = sourceWorldTranslation.x * -1 elif inMirrorAxis is 1: sourceWorldTranslation.y = sourceWorldTranslation.y * -1 elif inMirrorAxis is 2: sourceWorldTranslation.z = sourceWorldTranslation.z * -1 # Apply the mirrored position back to the target object. MFnTrans = OpenMaya.MFnTransform() targetDagPath = NodeUtility.getDagPath( inTargetObj ) MFnTrans.setObject( targetDagPath ) MFnTrans.setTranslation( sourceWorldTranslation, OpenMaya.MSpace.kWorld ) # Mirror the rotation. baseVectors = {} for row in xrange( 3 ): # We only need the first three rows. rowPtr = sourceRotationMatrix[row] baseVectors[ row ] = [] for col in xrange( 3 ): # We only need the first three columns. if col is not inMirrorAxis: origValue = OpenMaya.MScriptUtil.getDoubleArrayItem( rowPtr, col ) * -1 OpenMaya.MScriptUtil.setDoubleArray( rowPtr, col, origValue ) targetInverseMatrix = TransformUtility.getMatrix( inTargetObj, 'parentInverseMatrix' ) mirroredTarget = sourceRotationMatrix * targetInverseMatrix toEuler = OpenMaya.MTransformationMatrix( mirroredTarget ).eulerRotation() #x,y,z = map(math.degrees,(toEuler.x,toEuler.y,toEuler.z)) #print x,y,z MFnTrans.setRotation( toEuler )
def __init__( self, winName='createDeleteAttrUI' ): self.winTitle = 'Delete Attribute' self.winName = winName self.selList = cmds.ls( selection=True ) if len(self.selList) == 0: sys.stderr.write( 'An object isn\'t selected. Select one and try again.\n' ) return if len(self.selList) > 1: sys.stderr.write( 'To many objects ({0}) selected. Select only one object and try again.\n'.format( len(selList) ) ) return else: self.objName = NodeUtility.getDagPath( self.selList[0] ).fullPathName() self.doIt()
def setCurveCvs(inCurve, inCVArray): """ Sets a curves CVs to the values from inCVArray. @param inCurve: String. Name of curve to update. @param inCVArray: List of MPointArrays. """ curDag = NodeUtility.getDagPath(inCurve) curFn = OpenMaya.MFnNurbsCurve() childShapes = curDag.childCount() for child in xrange(childShapes): childObj = curDag.child(child) curFn.setObject(childObj) curFn.setCVs(inCVArray[child]) curFn.updateCurve()
def matchObjectTransforms( src, cld ): ''' Matches the child's translation and rotation to the source object. @param src: String. Name of the source transform object. @param cld: String. Name of the child object. ''' # do the matching of child to target MFnTrans = OpenMaya.MFnTransform() childDagPath = NodeUtility.getDagPath( cld ) MFnTrans.setObject( childDagPath ) targetMatrix = getMatrix( src, 'worldMatrix' ) childTranslation = getMatrixTranslation( targetMatrix, OpenMaya.MSpace.kWorld ) MFnTrans.setTranslation( childTranslation, OpenMaya.MSpace.kWorld ) childRotation = getMatrixRotation( targetMatrix, 'quat' ) MFnTrans.setRotation( childRotation, OpenMaya.MSpace.kWorld )
def createSpacer(inBitName, inGroupName="newGroup", inTargetObject=None, inDoParent=False, inPrefix=None): """ Creates an empty group. Optionally, the group's transforms can be matched to another object. @param inGroupName: String. Name to give the new group. @param inTargetObject: String. Name of object to match the group's transforms to. @return: The newly created group. """ # Create empty group. if inPrefix is not None: groupName = inPrefix + "_" + inGroupName else: groupName = inGroupName newGroup = cmds.group(em=True, name=groupName) # Set its transforms. if inTargetObject is not None: # Get target objects matrix. targetMatrix = TransformUtility.getMatrix(inTargetObject, "worldMatrix") # Get groups transform. MFnTrans = OpenMaya.MFnTransform() groupDagPath = NodeUtility.getDagPath(newGroup) MFnTrans.setObject(groupDagPath) # Apply the targets translation to the group. targetTranslation = TransformUtility.getMatrixTranslation(targetMatrix, OpenMaya.MSpace.kWorld) MFnTrans.setTranslation(targetTranslation, OpenMaya.MSpace.kWorld) # Apply the targets rotation to the group. targetRotation = TransformUtility.getMatrixRotation(targetMatrix, "quat") MFnTrans.setRotation(targetRotation, OpenMaya.MSpace.kWorld) # Parent the spacer. if inDoParent: parent = cmds.listRelatives(inBitName, parent=True) if NodeUtility.attributeCheck(parent[0], "controlName"): parentControl = NodeUtility.getFrameBitSettings(parent[0])["controlName"] cmds.parent(newGroup, parentControl, absolute=True) return newGroup
def applyXMLtoControl(): # Get the selected object. Only takes one object. sel = cmds.ls( selection=True, dagObjects=True, allPaths=True, transforms=True ) # Get the XML file. attrList = readControlXML() # Grab the shape node. transNode = NodeUtility.getDagPath( sel[0] ) MFnDepNode = OpenMaya.MFnDependencyNode() MFnDepNode.setObject( transNode.child( 0 ) ) if MFnDepNode.typeName() == 'ControlBox': # Update plugs with values, if any, from the command. NodeUtility.setPlugValue( MFnDepNode.findPlug( 'color' ), [ float( attrList[ 'color' ][ 'value' ][0] ), float( attrList[ 'color' ][ 'value' ][1] ), float( attrList[ 'color' ][ 'value' ][2] ) ] ) NodeUtility.setPlugValue( MFnDepNode.findPlug( 'localPosition' ), [ float( attrList[ 'localPosition' ][ 'value' ][0] ), float( attrList[ 'localPosition' ][ 'value' ][1] ), float( attrList[ 'localPosition' ][ 'value' ][2] ) ] ) NodeUtility.setPlugValue( MFnDepNode.findPlug( 'rotate' ), [ float( attrList[ 'rotate' ][ 'value' ][0] ), float( attrList[ 'rotate' ][ 'value' ][1] ), float( attrList[ 'rotate' ][ 'value' ][2] ) ] ) NodeUtility.setPlugValue( MFnDepNode.findPlug( 'transparency' ), float( attrList[ 'transparency' ][ 'value' ] ) ) NodeUtility.setPlugValue( MFnDepNode.findPlug( 'backAlpha' ), float( attrList[ 'backAlpha' ][ 'value' ] ) ) NodeUtility.setPlugValue( MFnDepNode.findPlug( 'lineWidth' ), int( attrList[ 'lineWidth' ][ 'value' ] ) ) NodeUtility.setPlugValue( MFnDepNode.findPlug( 'width' ), float( attrList[ 'width' ][ 'value' ] ) ) NodeUtility.setPlugValue( MFnDepNode.findPlug( 'height' ), float( attrList[ 'height' ][ 'value' ] ) ) NodeUtility.setPlugValue( MFnDepNode.findPlug( 'depth' ), float( attrList[ 'depth' ][ 'value' ] ) ) NodeUtility.setPlugValue( MFnDepNode.findPlug( 'drawType' ), int( attrList[ 'drawType' ][ 'value' ] ) ) NodeUtility.setPlugValue( MFnDepNode.findPlug( 'topFrontRight' ), [ float( attrList[ 'topFrontRight' ][ 'value' ][0] ), float( attrList[ 'topFrontRight' ][ 'value' ][1] ), float( attrList[ 'topFrontRight' ][ 'value' ][2] ) ] ) NodeUtility.setPlugValue( MFnDepNode.findPlug( 'topFrontLeft' ), [ float( attrList[ 'topFrontLeft' ][ 'value' ][0] ), float( attrList[ 'topFrontLeft' ][ 'value' ][1] ), float( attrList[ 'topFrontLeft' ][ 'value' ][2] ) ] ) NodeUtility.setPlugValue( MFnDepNode.findPlug( 'topBackRight' ), [ float( attrList[ 'topBackRight' ][ 'value' ][0] ), float( attrList[ 'topBackRight' ][ 'value' ][1] ), float( attrList[ 'topBackRight' ][ 'value' ][2] ) ] ) NodeUtility.setPlugValue( MFnDepNode.findPlug( 'topBackLeft' ), [ float( attrList[ 'topBackLeft' ][ 'value' ][0] ), float( attrList[ 'topBackLeft' ][ 'value' ][1] ), float( attrList[ 'topBackLeft' ][ 'value' ][2] ) ] ) NodeUtility.setPlugValue( MFnDepNode.findPlug( 'botFrontRight' ), [ float( attrList[ 'botFrontRight' ][ 'value' ][0] ), float( attrList[ 'botFrontRight' ][ 'value' ][1] ), float( attrList[ 'botFrontRight' ][ 'value' ][2] ) ] ) NodeUtility.setPlugValue( MFnDepNode.findPlug( 'botFrontLeft' ), [ float( attrList[ 'botFrontLeft' ][ 'value' ][0] ), float( attrList[ 'botFrontLeft' ][ 'value' ][1] ), float( attrList[ 'botFrontLeft' ][ 'value' ][2] ) ] ) NodeUtility.setPlugValue( MFnDepNode.findPlug( 'botBackRight' ), [ float( attrList[ 'botBackRight' ][ 'value' ][0] ), float( attrList[ 'botBackRight' ][ 'value' ][1] ), float( attrList[ 'botBackRight' ][ 'value' ][2] ) ] ) NodeUtility.setPlugValue( MFnDepNode.findPlug( 'botBackLeft' ), [ float( attrList[ 'botBackLeft' ][ 'value' ][0] ), float( attrList[ 'botBackLeft' ][ 'value' ][1] ), float( attrList[ 'botBackLeft' ][ 'value' ][2] ) ] )
def createFrameModuleXML(): # Browse for file to replace or new file to make. moduleFilter = "*.xml" dialogResults = cmds.fileDialog2( fileFilter=moduleFilter, dialogStyle=2, startingDirectory=XMLUtility.getPresetPath( XMLUtility.FRAME_PRESETS_PATH ) ) tempPath = dialogResults[0].split( '/' ) fullFileName = tempPath[ len( tempPath )-1 ] filePath = dialogResults[0].rstrip( fullFileName ) fileName = fullFileName.split( '.' )[0] # Get the name of the selected node and it's plugs. selList = cmds.ls( selection=True ) node = selList[0] nodeAttrs = getFrameBitSettings( node ) # Build a list with each entry representing a line in the XML file. xmlList = [] xmlList.append( '<data>' ) # Set the first line # Meta node. xmlList.append( '\t<metanode name=\"{0}\" metaType=\"{1}\" metaClass=\"{2}\">'.format( node, nodeAttrs['metaType'], nodeAttrs['metaClass'] ) ) # Loop through the attributes. for attr in nodeAttrs: plug = NodeUtility.getPlug( node, attr ) if plug.isConnected(): connection = NodeUtility.getNodeAttrSource( node, attr ) types = getAttrTypes( node, attr ) xmlList.append( '\t\t<plug name=\"{0}\" connected=\"{1}\" attrType=\"{2}\" attrDataType=\"{3}\">{4}</plug>'.format( attr, True, types[0], types[1], connection[0]+'.'+connection[1] ) ) else: types = getAttrTypes( node, attr ) xmlList.append( '\t\t<plug name=\"{0}\" connected=\"{1}\" attrType=\"{2}\" attrDataType=\"{3}\">{4}</plug>'.format( attr, False, types[0], types[1], NodeUtility.getPlugValue( plug ) ) ) xmlList.append( '\t</metanode>' ) # Get the root bit of the frame module. rootBit = NodeUtility.getNodeAttrSource( node, 'rootBit' ) if not rootBit: raise ValueError( 'The meta node\'s ({0}) ROOT BIT attribute is not connected.'.format(node) ) # Get the parent's full path. We need to remove the group name from the beginning as well. parent = cleanParentFullName( rootBit[0] ) xmlList.append( '\t<bit name=\"{0}\" parent=\"{1}\">'.format( rootBit[0], parent ) ) rootAttrs = getFrameBitSettings( rootBit[0] ) for attr in rootAttrs: types = getAttrTypes( rootBit[0], attr ) plug = NodeUtility.getPlug( rootBit[0], attr ) xmlList.append( '\t\t<plug name=\"{0}\" attrType=\"{1}\" attrDataType=\"{2}\">{3}</plug>'.format( attr, types[0], types[1], NodeUtility.getPlugValue( plug ) ) ) wmRootBit = TransformUtility.getMatrix( rootBit[0], 'matrix' ) pos = TransformUtility.getMatrixTranslation( wmRootBit, OpenMaya.MFn.kWorld ) rot = TransformUtility.getMatrixRotation( wmRootBit, 'eulerVector' ) xmlList.append( '\t\t<plug name=\"translateX\">{0}</plug>'.format( pos.x ) ) xmlList.append( '\t\t<plug name=\"translateY\">{0}</plug>'.format( pos.y ) ) xmlList.append( '\t\t<plug name=\"translateZ\">{0}</plug>'.format( pos.z ) ) xmlList.append( '\t\t<plug name=\"rotateX\">{0}</plug>'.format( math.degrees(rot.x) ) ) xmlList.append( '\t\t<plug name=\"rotateY\">{0}</plug>'.format( math.degrees(rot.y) ) ) xmlList.append( '\t\t<plug name=\"rotateZ\">{0}</plug>'.format( math.degrees(rot.z) ) ) # Shape nodes attributes. rootShape = NodeUtility.getDagPath( rootBit[0] ).child( 0 ) depFn = OpenMaya.MFnDependencyNode( rootShape ) shapeName = cmds.listRelatives( rootBit[0], shapes=True, fullPath=True )[0] shapeType = depFn.typeName() xmlList.append( '\t\t<shape name=\"{0}\">'.format( shapeType ) ) # Get the shape's local position and scale. for attr in cmds.listAttr( shapeName, channelBox=True ): types = getAttrTypes( shapeName, attr ) aPlug = NodeUtility.getPlug( shapeName, attr ) xmlList.append( '\t\t\t<plug name=\"{0}\" attrType=\"{1}\" attrDataType=\"{2}\">{3}</plug>'.format( attr, types[0], types[1], NodeUtility.getPlugValue(aPlug) ) ) # Get the shape's custom attributes. for attr in cmds.listAttr( shapeName, multi=True, keyable=True ): if attr.find( '[' ) is not -1: # Special case handle array attributes. The [] needs to be removed so we can get # the base name for the attribute. From there we can then loop through it's children. # First we get the connection since these plugs won't return a value, but rather a # connected node. connection = NodeUtility.getNodeAttrSource( shapeName, attr ) bitChildren = cmds.listRelatives( rootBit[0], type='transform', children=True, fullPath=True ) for child in bitChildren: if child.find( connection[0] ): plugValue = child # Now we get the compound attribute's name by removing the index brackets. attrSplit = attr.split('[') attr = attrSplit[0] else: aPlug = NodeUtility.getPlug( shapeName, attr ) plugValue = NodeUtility.getPlugValue( aPlug ) types = getAttrTypes( shapeName, attr ) if types[0] is not False: xmlList.append( '\t\t\t<plug name=\"{0}\" attrType=\"{1}\" attrDataType=\"{2}\">{3}</plug>'.format( attr, types[0], types[1], plugValue ) ) xmlList.append( '\t\t</shape>' ) xmlList.append( '\t</bit>') # Get all of the root's children. children = getFrameRootAllChildren( rootBit[0] ) for child in children: # Bit name. bitName = child parent = cleanParentFullName( child ) childFrameAttrs = getFrameBitSettings( child ) xmlList.append( '\t<bit name=\"{0}\" parent=\"{1}\">'.format( bitName, parent ) ) # Transform nodes attributes. if childFrameAttrs is not None: for attr in childFrameAttrs: types = getAttrTypes( child, attr ) plug = NodeUtility.getPlug( child, attr ) xmlList.append( '\t\t<plug name=\"{0}\" attrType=\"{1}\" attrDataType=\"{2}\">{3}</plug>'.format( attr, types[0], types[1], NodeUtility.getPlugValue( plug ) ) ) # Get the position and rotation. wmBit = TransformUtility.getMatrix( child, 'matrix' ) pos = TransformUtility.getMatrixTranslation( wmBit, OpenMaya.MFn.kWorld ) rot = TransformUtility.getMatrixRotation( wmBit, 'eulerVector' ) xmlList.append( '\t\t<plug name=\"translateX\">{0}</plug>'.format( pos.x ) ) xmlList.append( '\t\t<plug name=\"translateY\">{0}</plug>'.format( pos.y ) ) xmlList.append( '\t\t<plug name=\"translateZ\">{0}</plug>'.format( pos.z ) ) xmlList.append( '\t\t<plug name=\"rotateX\">{0}</plug>'.format( math.degrees(rot.x) ) ) xmlList.append( '\t\t<plug name=\"rotateY\">{0}</plug>'.format( math.degrees(rot.y) ) ) xmlList.append( '\t\t<plug name=\"rotateZ\">{0}</plug>'.format( math.degrees(rot.z) ) ) # Shape nodes attributes. childShape = NodeUtility.getDagPath( child ).child( 0 ) depFn = OpenMaya.MFnDependencyNode( childShape ) shapeName = cmds.listRelatives( child, shapes=True, fullPath=True )[0] shapeType = depFn.typeName() xmlList.append( '\t\t<shape name=\"{0}\">'.format( shapeType ) ) # Get the shape's local position and scale. for attr in cmds.listAttr( shapeName, channelBox=True ): types = getAttrTypes( shapeName, attr ) aPlug = NodeUtility.getPlug( shapeName, attr ) xmlList.append( '\t\t\t<plug name=\"{0}\" attrType=\"{1}\" attrDataType=\"{2}\">{3}</plug>'.format( attr, types[0], types[1], NodeUtility.getPlugValue(aPlug) ) ) # Get the shape's custom attributes. for attr in cmds.listAttr( shapeName, multi=True, keyable=True ): if attr.find( '[' ) is not -1: # Special case handle array attributes. The [] needs to be removed so we can get # the base name for the attribute. From there we can then loop through it's children. # First we get the connection since these plugs won't return a value, but rather a # connected node. connection = NodeUtility.getNodeAttrSource( shapeName, attr ) bitChildren = cmds.listRelatives( child, type='transform', children=True, fullPath=True ) for c in bitChildren: if c.find( connection[0] ): plugValue = c # Now we get the compound attribute's name by removing the index brackets. attrSplit = attr.split('[') attr = attrSplit[0] else: aPlug = NodeUtility.getPlug( shapeName, attr ) plugValue = NodeUtility.getPlugValue( aPlug ) types = getAttrTypes( shapeName, attr ) if types[0] is not False: xmlList.append( '\t\t\t<plug name=\"{0}\" attrType=\"{1}\" attrDataType=\"{2}\">{3}</plug>'.format( attr, types[0], types[1], plugValue ) ) xmlList.append( '\t\t</shape>' ) # Close the bit. xmlList.append( '\t</bit>' ) # Close the data tag. xmlList.append( '</data>' ) # Create the new file. newfile = file( os.path.join( filePath, fullFileName ), 'w') for i in xmlList: newfile.write( i+'\n' ) newfile.close()
def writeModuleXML( inRootObjectName, inModuleType, inModuleName ): ''' Function for writing module xml. @param inRootObjectName: String. Name of module root object. @param inModuleType: String. Type of module. This determines which sub-folder the XML is saved. @param inModuleName: String. Name of the module XML file. ''' # Get list of the module hierarchy. Root is always first hierarchyList = NodeUtility.getFrameRootAllChildren( inRootObjectName ) hierarchyList.insert( 0, inRootObjectName ) # START: Writing XML xmlLines = [] xmlLines.append( '<data>' ) for item in hierarchyList: # BIT INFO itemName = getObjectShortName( item ) itemParent = NodeUtility.cleanParentFullName( item ) itemMatrix = TransformUtility.getMatrix( item, 'matrix' ) itemPosition = TransformUtility.getMatrixTranslation( itemMatrix, OpenMaya.MSpace.kTransform ) itemRotation = TransformUtility.getMatrixRotation( itemMatrix, 'eulerVector' ) # START: Bit xmlLines.append( '\t<bit name=\"{0}\" parent=\"{1}\">'.format( itemName, itemParent ) ) xmlLines.append( '\t\t<plug name=\"translateX\">{0}</plug>'.format( itemPosition.x ) ) xmlLines.append( '\t\t<plug name=\"translateY\">{0}</plug>'.format( itemPosition.y ) ) xmlLines.append( '\t\t<plug name=\"translateZ\">{0}</plug>'.format( itemPosition.z ) ) xmlLines.append( '\t\t<plug name=\"rotateX\">{0}</plug>'.format( math.degrees(itemRotation.x) ) ) xmlLines.append( '\t\t<plug name=\"rotateY\">{0}</plug>'.format( math.degrees(itemRotation.y) ) ) xmlLines.append( '\t\t<plug name=\"rotateZ\">{0}</plug>'.format( math.degrees(itemRotation.z) ) ) # SHAPE itemShape = NodeUtility.getDagPath( itemName ).child( 0 ) depFn = OpenMaya.MFnDependencyNode( itemShape ) shapeType = depFn.typeName() if shapeType.find( 'gl' ) != -1: itemShapeName = cmds.listRelatives( itemName, shapes=True, fullPath=True )[0] # Start shape xmlLines.append( '\t\t<shape name=\"{0}\">'.format( shapeType ) ) # Get the shape's local position and scale. for attr in cmds.listAttr( itemShapeName, channelBox=True ): types = NodeUtility.getAttrTypes( itemShapeName, attr ) aPlug = NodeUtility.getPlug( itemShapeName, attr ) xmlLines.append( '\t\t\t<plug name=\"{0}\" attrType=\"{1}\" attrDataType=\"{2}\">{3}</plug>'.format( attr, types[0], types[1], NodeUtility.getPlugValue(aPlug) ) ) # Get the shape's custom attributes. for attr in cmds.listAttr( itemShapeName, multi=True, keyable=True ): types = NodeUtility.getAttrTypes( itemShapeName, attr ) if attr.find( '[' ) is not -1: # Special case handle array attributes. The [] needs to be removed so we can get # the base name for the attribute. From there we can then loop through it's children. # First we get the connection since these plugs won't return a value, but rather a # connected node. connection = NodeUtility.getNodeAttrSource( itemShapeName, attr ) bitChildren = cmds.listRelatives( itemName, type='transform', children=True, fullPath=True ) for child in bitChildren: childSplit = child.split('|') if childSplit[-1] == connection[0]: plugValue = child # Now we get the compound attribute's name by removing the index brackets. attrSplit = attr.split('[') attr = attrSplit[0] else: aPlug = NodeUtility.getPlug( itemShapeName, attr ) plugValue = NodeUtility.getPlugValue( aPlug ) if types[0] is not False: xmlLines.append( '\t\t\t<plug name=\"{0}\" attrType=\"{1}\" attrDataType=\"{2}\">{3}</plug>'.format( attr, types[0], types[1], plugValue ) ) # End shape xmlLines.append( '\t\t</shape>' ) # BIT COMPONENTS print 'item: {0}'.format( item ) bitComponents = components.getComponents( item ) for comp in bitComponents: # Component info compName = ''.join(i for i in comp if not i.isdigit()) # Start component. xmlLines.append( '\t\t<component name=\"{0}\">'.format( compName ) ) compSettings = NodeUtility.getModuleComponentSettings( comp ) for attr in compSettings: types = NodeUtility.getAttrTypes( comp, attr ) # Special case message plugs. if types[1] == 'message': messageValues = NodeUtility.getAttrMessageValue( comp, attr ) if isinstance( messageValues, unicode ): plugValue = messageValues elif isinstance( messageValues, list ): plugValue = None else: aPlug = NodeUtility.getPlug( comp, attr ) plugValue = NodeUtility.getPlugValue( aPlug ) xmlLines.append( '\t\t\t<plug name=\"{0}\" attrType=\"{1}\" attrDataType=\"{2}\">{3}</plug>'.format( attr, types[0], types[1], plugValue ) ) xmlLines.append( '\t\t</component>' ) # END: Bit xmlLines.append( '\t</bit>' ) # END: Writing XML xmlLines.append( '</data>' ) # Create the file startingDirectory = getPresetPath( FRAME_PRESETS_PATH ) filePath = '{0}{1}'.format( startingDirectory, inModuleType ) fileName = '{0}.xml'.format( inModuleName ) newfile = file( os.path.join( filePath, fileName ), 'w') for i in xmlLines: newfile.write( i+'\n' ) newfile.close()
def createControlXML(): ''' Creates/updates module XML file. ''' # Controller attributes. cAttr = [ 'color', 'localPosition', 'rotate', 'transparency', 'backAlpha', 'lineWidth', 'width', 'height', 'depth', 'drawType', 'topFrontRight', 'topFrontLeft', 'topBackRight', 'topBackLeft', 'botFrontRight', 'botFrontLeft', 'botBackRight', 'botBackLeft' ] # Browse for file to replace or new file to make. moduleFilter = "*.xml" dialogResults = cmds.fileDialog2( fileFilter=moduleFilter, dialogStyle=2, startingDirectory=getPresetPath( CONTROLLER_PRESETS_PATH ) ) tempPath = dialogResults[0].split( '/' ) fileName = tempPath[ len( tempPath )-1 ] filePath = dialogResults[0].rstrip( fileName ) objName = fileName.split( '.' )[0] # Get the selected object. Only takes one object. sel = cmds.ls( selection=True, dagObjects=True, allPaths=True, transforms=True ) # Build a list for each line in an XML file. xmlList = [] xmlList.append( '<data>' ) # Grab the shape node. transNode = NodeUtility.getDagPath( sel[0] ) shapeNode = transNode.child( 0 ) MFnDagNode = OpenMaya.MFnDagNode() MFnDagNode.setObject( shapeNode ) # Get the attributes and format them for the XML file. if MFnDagNode.typeName() == 'ControlBox': # Create a <control>. xmlList.append( '\t<control name=\"{0}\" type=\"{1}\">'.format( sel[0], MFnDagNode.typeName() ) ) xmlList.append( '\t</control>' ) for a in cAttr: # Get the attributes. xmlList.insert( len( xmlList ) - 1, '\t\t<attr name=\"{0}">'.format( a ) ) plug = NodeUtility.getPlug( MFnDagNode.name(), a ) plugValue = NodeUtility.getPlugValue( plug ) if isinstance( plugValue, types.ListType ): for i in plugValue: xmlList.insert( len( xmlList ) - 1, '\t\t\t<value>{0}</value>'.format( i ) ) else: xmlList.insert( len( xmlList ) - 1, '\t\t\t<value>{0}</value>'.format( plugValue ) ) xmlList.insert( len( xmlList ) - 1, '\t\t</attr>' ) # close the data tag xmlList.append( '</data>' ) # create new file newfile = file( os.path.join( filePath, fileName ), 'w') for i in xmlList: newfile.write( i+'\n' ) newfile.close()
def buildModule(): ''' Build function for all the rigging associated with this module. ''' # Get the frame module meta nodes in the scene. modules = NodeUtility.getMetaNodesInScene( 'frameModule' ) # Read the meta node. nodeData = NodeUtility.getFrameBitSettings( modules[0] ) prefix = nodeData['prefix'] # Get the frame module bits. frameRoot = NodeUtility.getNodeAttrSource( modules[0], 'rootBit' )[0] shoulderBit = NodeUtility.getNodeAttrSource( modules[0], 'jShoulder' )[0] elbowBit = NodeUtility.getNodeAttrSource( modules[0], 'jElbow' )[0] wristBit = NodeUtility.getNodeAttrSource( modules[0], 'jWrist' )[0] ikRootBit = NodeUtility.getNodeAttrSource( modules[0], 'ikRoot' )[0] ikEndBit = NodeUtility.getNodeAttrSource( modules[0], 'ikEnd' )[0] ikUpVecBit = NodeUtility.getNodeAttrSource( modules[0], 'ikUpVecControl' )[0] # Build shadow skeleton. jointShoulder = marigoldJoints.createJoint( nodeData['jShoulder'], shoulderBit, inPrefix=prefix ) jointElbow = marigoldJoints.createJoint( nodeData['jElbow'], elbowBit, jointShoulder, inPrefix=prefix ) jointWrist = marigoldJoints.createJoint( nodeData['jWrist'], wristBit, jointElbow, inPrefix=prefix ) # Make the FK rigging. fkControls = [ [nodeData['fkShoulderControl'], nodeData['fkShoulderControlName'], nodeData['jShoulder'], shoulderBit], [nodeData['fkElbowControl'], nodeData['fkElbowControlName'], nodeData['jElbow'],elbowBit] ] for i in fkControls: # Create the spacer. spacerName = 'j_{0}_{1}'.format( prefix, i[2] ) newSpacer = marigoldControls.makeControl().createSpacer( i[3], i[1], spacerName, True ) # Create the controller. controlSplit = i[0].split( '.' ) marigoldControls.makeControl().createController( controlSplit[0], controlSplit[1], i[1], newSpacer ) # Make the IK rigging. effSplit = nodeData['ikEffControl'].split('.') effSpacer = marigoldControls.makeControl().createSpacer( ikEndBit, nodeData['ikEffControlName'], 'j_'+prefix+'_'+nodeData['jWrist'], inDoParent=False, inPrefix=prefix ) marigoldControls.makeControl().createController( effSplit[0], effSplit[1], nodeData['ikEffControlName'], effSpacer, inPrefix=prefix ) upVecSplit = nodeData['ikUpVecControl'].split('.') upVecSpacer = marigoldControls.makeControl().createSpacer( ikUpVecBit, nodeData['ikUpVecControlName'], ikUpVecBit, inDoParent=False, inPrefix=prefix ) marigoldControls.makeControl().createController( upVecSplit[0], upVecSplit[1], nodeData['ikUpVecControlName'], upVecSpacer, inPrefix=prefix ) jointFn = OpenMayaAnim.MFnIkJoint() # IK root joint. jointShoulder = 'j_{0}_{1}'.format( prefix, nodeData['jShoulder'] ) rootJointDagPath = NodeUtility.getDagPath( jointShoulder ) # IK eff joint. jointWrist = 'j_{0}_{1}'.format( prefix, nodeData['jWrist'] ) effJointDagPath = NodeUtility.getDagPath( jointWrist ) # Do up the solver. ikHandleName = '{0}_{1}_arm'.format( nodeData['ikEffControlName'], prefix ) cmds.ikHandle( name=ikHandleName, startJoint=rootJointDagPath.fullPathName(), endEffector=effJointDagPath.fullPathName(), solver='ikRPsolver' ) effControlName = 'ct_{0}_{1}'.format( prefix, nodeData['ikEffControlName'] ) cmds.parent( ikHandleName, effControlName, absolute=True ) upVecControlName = 'ct_{0}_{1}'.format( prefix, nodeData['ikUpVecControlName'] ) cmds.poleVectorConstraint( upVecControlName, ikHandleName )