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 storeControlTransforms( sourceObj, targetObj ): ''' Store control transform data. @param sourceObj: String. Name of object to pull data from. @param targetObj: String. Name of object to store data on. ''' sourceMatrix = TransformUtility.getMatrix( sourceObj, 'matrix' ) # Store the position targetPosPlug = NodeUtility.getPlug( targetObj, 'controlPosition' ) sourceTranslation = TransformUtility.getMatrixTranslation( sourceMatrix, OpenMaya.MSpace.kTransform ) pos = [ sourceTranslation.x, sourceTranslation.y, sourceTranslation.z ] NodeUtility.setPlugValue( targetPosPlug, pos ) # Store the rotation targetRotPlug = NodeUtility.getPlug( targetObj, 'controlRotation' ) sourceRotation = TransformUtility.getMatrixRotation( sourceMatrix, 'euler' ) #rot = [ degrees(angle) for angle in (sourceRotation.x, sourceRotation.y, sourceRotation.z) ] rot = [ sourceRotation.x, sourceRotation.y, sourceRotation.z ] NodeUtility.setPlugValue( targetRotPlug, rot ) # Store the scale. targetSclPlug = NodeUtility.getPlug( targetObj, 'controlScale' ) sourceScale = TransformUtility.getMatrixScale( sourceMatrix, OpenMaya.MSpace.kTransform ) scl = [ sourceScale.x, sourceScale.y, sourceScale.z ] NodeUtility.setPlugValue( targetSclPlug, scl )
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 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 createJoint( inJointName, inJointRef, inJointParent=None, inJointRadius=4.0, inPrefix=None ): ''' Creates a single joint. @param inBit: String. Name of the frame bit. @param inParent: MObject. Parent MObject for the new joint. @return: The MObject of the joint created. ''' # Create the joint. dagMod = OpenMaya.MDagModifier() if inJointParent: newJoint = dagMod.createNode( 'joint', inJointParent ) else: newJoint = dagMod.createNode( 'joint' ) dagMod.doIt() # Name the joint. if inPrefix is None: jointName = inJointName else: jointName = inPrefix+'_'+inJointName depFn = OpenMaya.MFnDependencyNode( newJoint ) depFn.setName( jointName ) # Modify the joint. jointFn = OpenMayaAnim.MFnIkJoint() jointFn.setObject( newJoint ) parentDepNode = OpenMaya.MFnDependencyNode( jointFn.parent( 0 ) ) bitLocalMatrix = TransformUtility.getMatrix( inJointRef, 'matrix' ) bitWorldMatrix = TransformUtility.getMatrix( inJointRef, 'worldMatrix' ) # Set orientation. if parentDepNode.name() == 'world': #print 'set world euler' bitEuler = TransformUtility.getMatrixRotation( bitWorldMatrix, 'euler' ) jointFn.setOrientation( bitEuler ) else: #print 'set local euler' bitEuler = TransformUtility.getMatrixRotation( bitLocalMatrix, 'euler' ) jointFn.setOrientation( bitEuler ) # Set position. bitWorldTranslationVector = TransformUtility.getMatrixTranslation( bitWorldMatrix, OpenMaya.MSpace.kWorld ) if parentDepNode.name() == 'world': # If the joint's parent is the world, then we take the translation vector straight # from the frame bit's world matrix. jointVector = bitWorldTranslationVector space = OpenMaya.MSpace.kTransform else: # If the joint's parent is another joint, then we need to get the parent's world # matrix and use it as a change of basis for the frame bit's world matrix. parentMatrix = TransformUtility.getMatrix( parentDepNode.name(), 'worldMatrix' ) basisMatrix = bitWorldMatrix * parentMatrix.inverse() jointVector = TransformUtility.getMatrixTranslation( basisMatrix, OpenMaya.MSpace.kWorld ) space = OpenMaya.MSpace.kWorld jointFn.setTranslation( jointVector, space ) # Set rotation order. # TODO # Set rotation. #if parentDepNode.name() == 'world': #print 'set world euler' #bitEuler = TransformUtility.getMatrixRotation( bitWorldMatrix, 'euler' ) #jointFn.setRotation( bitEuler ) #else: #print 'set local euler' #bitEuler = TransformUtility.getMatrixRotation( bitLocalMatrix, 'euler' ) #jointFn.setRotation( bitEuler ) # Set preferred angle. # TODO # Set joint radius. cmds.setAttr( jointName+'.radius', inJointRadius ) return newJoint
print 'Row 1: {0}'.format( row1 ) print 'Row 2: {0}'.format( row2 ) print 'Row 3: {0}'.format( row3 ) print 'Row 4: {0}'.format( row4 ) ## setup double[4][4] fileTran = [-10.330358779423445, 3.5726726411932432, 7.329368248748317] fileRotMatrix = [0.9035851814735454, -0.41914955150032557, -0.08858596558426181, 0.0] fileRotMatrix.extend([0.4263705359882413, 0.8999962921054725, 0.09063575584448433, 0.0]) fileRotMatrix.extend([0.04173710414631, -0.11966757151992792, 0.991936331860066, 0.0]) fileRotMatrix.extend([0.0, 0.0, 0.0, 1.0]) util = OpenMaya.MScriptUtil() mat = TransformUtility.getMatrix( 'pSphere1', 'worldMatrix' ) rotMat = OpenMaya.MTransformationMatrix( mat ).asRotateMatrix() ## create a zero matrix matrixZero = OpenMaya.MMatrix() ## set the zero matrix to the file values rotMatT = OpenMaya.MTransformationMatrix( rotMat ) x = util.asDoublePtr() y = util.asDoublePtr() z = util.asDoublePtr() w = util.asDoublePtr() rotMatT.getRotationQuaternion(x,y,z,w) print y print util.getDouble(y) quat = OpenMaya.MQuaternion(util.getDouble(x),