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 bitsGUI( self ): col = cmds.columnLayout( adjustableColumn=True, columnAttach=('both', 5), parent=self.fillArea ) cmds.separator( style='none', height=4, width=413 ) # Primitives section. cmds.text( label='BIT PRIMITIVES', height=20, font='boldLabelFont', backgroundColor=[0.2,0.2,0.2] ) cmds.separator( style='none', height=5 ) cmds.gridLayout( numberOfColumns=5, cellWidthHeight=( 50, 50 ) ) cmds.button( label='Sphere', command=lambda b, a1='glSphere': cmds.makeGLBit( objecttype=a1 ) ) cmds.button( label='Box', command=lambda b, a1='glBox': cmds.makeGLBit( objecttype=a1 ) ) cmds.button( label='Cylinder', command=lambda b, a1='glCylinder': cmds.makeGLBit( objecttype=a1 ) ) cmds.button( label='Cone', command=lambda b, a1='glCone': cmds.makeGLBit( objecttype=a1 ) ) cmds.button( label='Torus', command=lambda b, a1='glTorus': cmds.makeGLBit( objecttype=a1 ) ) cmds.setParent( '..' )#gridLayout cmds.separator( style='none', height=10 ) # Transform section. cmds.text( label='TRANSFORM TOOLS', height=20, font='boldLabelFont', backgroundColor=[0.2,0.2,0.2] ) cmds.separator( style='none', height=5 ) cmds.gridLayout( numberOfColumns=3, cellWidthHeight=( 50, 50 ) ) cmds.iconTextButton( annotation='match translation', style='iconOnly', image1='icon_match_translation.png', command=lambda a1='tran': TransformUtility.matchTransforms(a1) ) cmds.iconTextButton( annotation='match rotation', style='iconOnly', image1='icon_match_rotation.png', label='match rotation', command=lambda a1='rot': TransformUtility.matchTransforms(a1) ) cmds.iconTextButton( annotation='match all', style='iconOnly', image1='icon_match_all.png', label='match all', command=lambda a1='all': TransformUtility.matchTransforms(a1) ) cmds.setParent( '..' )#gridLayout cmds.separator( style='none', height=10 ) cmds.setParent( '..' )#col
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 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 doIt( self, *args ): # ui settings. self.winWidth = 306 self.winHeight = 400 self.iconWidth = 32 self.iconHeight = 32 # clean up old uis before opening a new one. try: cmds.deleteUI( self.winName ) except: pass self.mainWindow = cmds.window( self.winName, title=self.winTitle, sizeable=False, resizeToFitChildren=False ) cmds.frameLayout( borderVisible=False, labelVisible=False ) self.conTools = cmds.columnLayout( height=self.winHeight/3 ) cmds.text( label='Controller Tools', width=self.winWidth, wordWrap=True, align='center', font='boldLabelFont', backgroundColor=(0.15,0.15,0.15) ) cmds.separator( style='none', height=4 ) self.conGrid = cmds.gridLayout( numberOfColumns=4, numberOfRows=2, cellWidthHeight=(self.winWidth/4, 50) ) cmds.button( label='Make Control', command='cmds.rigController()' ) cmds.button( label='Make From XML', command='XMLUtility.createControlFromXML()' ) cmds.button( label='Apply XML', command='XMLUtility.applyXMLtoControl()' ) cmds.button( label='Save XML', command='XMLUtility.createControlXML()' ) cmds.button( label='Make Deformer', command='makeDeformerMesh()') cmds.button( label='Apply Deformer', command='applyDeformerMesh()') cmds.setParent( '..' )#self.conGrid cmds.separator( style='none', height=20 ) cmds.text( label='Position Tools', width=self.winWidth, wordWrap=True, align='center', font='boldLabelFont', backgroundColor=(0.15,0.15,0.15) ) cmds.separator( style='none', height=4 ) self.transGrid = cmds.gridLayout( numberOfColumns=3, cellWidthHeight=(self.winWidth/3, 50) ) cmds.button( label='Match Translation', command=lambda *args: TransformUtility.matchTransforms( 'tran' ) ) cmds.button( label='Match Rotation', command=lambda *args: TransformUtility.matchTransforms( 'rot' ) ) cmds.button( label='Match All', command=lambda *args: TransformUtility.matchTransforms( 'all' ) ) cmds.setParent( '..' )#self.transGrid cmds.setParent( '..' )#self.conTools cmds.setParent( '..' )#framelayout # show the ui. cmds.showWindow( self.winName )
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 doIt( self, *args ): # Window settings. self.winWidth = 206 self.winHeight = 400 self.iconWidth = 32 self.iconHeight = 32 # Window colors self.rowColors = [[0.4,0.4,0.4],[0.5,0.5,0.5]] # Clean up old uis before opening a new one. try: cmds.deleteUI( self.winName ) except: pass # Setup the form layout. self.mainWindow = cmds.window( self.winName, title=self.winTitle, sizeable=False, resizeToFitChildren=False ) self.form = cmds.formLayout() self.tabs = cmds.tabLayout( innerMarginWidth=5, innerMarginHeight=5 ) # Attach the tabs layout to the form layout. cmds.formLayout( self.form, edit=True, attachForm=( (self.tabs, 'top', 0), (self.tabs, 'left', 0), (self.tabs, 'bottom', 0), (self.tabs, 'right', 0) ) ) # Create each of the tabs. # TAB: META NODES: START self.tabMeta = cmds.rowColumnLayout( numberOfRows=2, width=self.winWidth ) self.colMeta = cmds.rowColumnLayout( numberOfColumns=1, height=self.winHeight/2 ) cmds.text( label='Meta Nodes', width=self.winWidth, wordWrap=True, align='center', font='boldLabelFont', backgroundColor=(0.15,0.15,0.15) ) cmds.separator( style='none', height=4 ) self.gridMeta = cmds.gridLayout( numberOfColumns=4, cellWidthHeight=( 50, 50 ) ) cmds.button( label='Basic', command=lambda b, a1='frameModule': metaNode.MetaNode( inNodeMetaType=a1 ) ) cmds.button( label='Character', command=lambda b, a1=False: metaNode.MetaCharacter( doModel=a1 ) ) cmds.setParent( '..' )#self.gridMeta cmds.setParent( '..' )#self.colMeta self.colMetaTools = cmds.rowColumnLayout( numberOfColumns=1 ) cmds.text( label='Tools', width=self.winWidth, wordWrap=True, align='center', font='boldLabelFont', backgroundColor=(0.15,0.15,0.15) ) cmds.separator( style='none', height=4 ) self.rowMetaTools = cmds.rowColumnLayout( numberOfRows=1 ) cmds.button( label='Meta Node List', annotation='meta node list', command=lambda b: SelectMetaUI.selectMetaUI() ) cmds.setParent( '..' )#self.rowMetaTools cmds.setParent( '..' )#self.colMetaTools cmds.setParent( '..' )#self.tabMeta # TAB: META NODES: END # TAB: BITS, START self.tabBits = cmds.rowColumnLayout( numberOfRows=3, width=self.winWidth ) self.bitsCol = cmds.rowColumnLayout( numberOfColumns=1, height=self.winHeight/3 ) cmds.text( label='Bit Primitives', width=self.winWidth, wordWrap=True, align='center', font='boldLabelFont', backgroundColor=(0.15,0.15,0.15) ) cmds.separator( style='none', height=4 ) self.bitsGrid = cmds.gridLayout( numberOfColumns=4, cellWidthHeight=( 50, 50 ) ) cmds.button( label='Sphere', command=lambda b, a1='glSphere': cmds.makeGLBit( objecttype=a1 ) ) cmds.button( label='Box', command=lambda b, a1='glBox': cmds.makeGLBit( objecttype=a1 ) ) cmds.button( label='Cylinder', command=lambda b, a1='glCylinder': cmds.makeGLBit( objecttype=a1 ) ) cmds.button( label='Cone', command=lambda b, a1='glCone': cmds.makeGLBit( objecttype=a1 ) ) cmds.button( label='Torus', command=lambda b, a1='glTorus': cmds.makeGLBit( objecttype=a1 ) ) cmds.setParent( '..' )#self.bitsGrid cmds.setParent( '..' )#self.bitsCol self.toolsCol = cmds.rowColumnLayout( numberOfColumns=1 ) cmds.text( label='Transform Tools', width=self.winWidth, wordWrap=True, align='center', font='boldLabelFont', backgroundColor=(0.15,0.15,0.15) ) cmds.separator( style='none', height=4 ) self.toolRow = cmds.rowColumnLayout( numberOfRows=1 ) cmds.iconTextButton( annotation='match translation', style='iconOnly', width=self.winWidth/3, image1='icon_match_translation.png', command=lambda a1='tran': TransformUtility.matchTransforms(a1) ) cmds.iconTextButton( annotation='match rotation', style='iconOnly', width=self.winWidth/3, image1='icon_match_rotation.png', label='match rotation', command=lambda a1='rot': TransformUtility.matchTransforms(a1) ) cmds.iconTextButton( annotation='match all', style='iconOnly', width=self.winWidth/3, image1='icon_match_all.png', label='match all', command=lambda a1='all': TransformUtility.matchTransforms(a1) ) cmds.setParent( '..' )#self.toolRow cmds.setParent( '..' )#self.toolsCol self.childCol = cmds.rowColumnLayout( numberOfColumns=1 ) cmds.text( label='General Tools', width=self.winWidth, wordWrap=True, align='center', font='boldLabelFont', backgroundColor=(0.15,0.15,0.15) ) cmds.separator( style='none', height=4 ) self.childRow = cmds.rowColumnLayout( numberOfColumns=2 ) cmds.button( label='Add Child', command=lambda b: NodeUtility.setBitChild() ) cmds.button( label='Remove Child', command=lambda b: NodeUtility.deleteBitChild() ) cmds.button( label='Copy Settings', command=lambda b: NodeUtility.copyBitSettings() ) cmds.setParent( '..' )#self.childRow cmds.setParent( '..' )#self.childCol cmds.setParent( '..' )#self.tabBits # TAB: BITS, END # TAB: ATTRIBUTES, START self.tabAttrs = cmds.rowColumnLayout( numberOfRows=2 ) # Top self.attrTop = cmds.rowColumnLayout( numberOfColumns=1 ) cmds.text( label='Attribute List', width=self.winWidth, wordWrap=True, align='center', font='boldLabelFont', backgroundColor=(0.15,0.15,0.15) ) cmds.separator( style='none', height=4 ) # Top rows. self.attrList = cmds.scrollLayout( horizontalScrollBarThickness=16, verticalScrollBarThickness=16, height=150 ) self.fillAttrList() cmds.setParent( '..' )#attrList # Bottom buttons cmds.rowColumnLayout( numberOfColumns=2 ) #cmds.button( label='Add Custom Attribute' ) cmds.button( label='Delete Attributes', command=lambda b: deleteAttrUI.createDeleteAttrUI() ) cmds.button( label='Add Selected', command=lambda b: self.addAttrsFromList() ) cmds.separator( style='none', height=10 ) cmds.setParent( '..' )#button columns cmds.setParent( '..' )#self.attrTop self.attrPresets = cmds.rowColumnLayout( numberOfColumns=1 ) cmds.text( label='Attribute Presets', width=self.winWidth, wordWrap=True, align='center', font='boldLabelFont', backgroundColor=(0.15,0.15,0.15) ) cmds.separator( style='none', height=4 ) self.presets = cmds.gridLayout( numberOfColumns=4, cellWidthHeight=( 50, 50 ) ) self.fillAttrPresets() cmds.setParent( '..' )#self.presets cmds.setParent( '..' )#self.attrPresets cmds.setParent( '..' )#self.tabAttrs # TAB: ATTRIBUTES, END # TAB: XML: START self.tabXML = cmds.rowColumnLayout( numberOfRows=2, width=self.winWidth ) self.colXML = cmds.rowColumnLayout( numberOfColumns=1, height=self.winHeight/2 ) cmds.text( label='XML Tools', width=self.winWidth, wordWrap=True, align='center', font='boldLabelFont', backgroundColor=(0.15,0.15,0.15) ) cmds.separator( style='none', height=4 ) cmds.button( label='Save Frame Module XML', command=lambda b: FrameUtility.createFrameModuleXML() ) cmds.setParent( '..' )#self.colXML cmds.setParent( '..' )#self.tabXML # TAB: XML: END # Added the tabs to the tab layout. cmds.tabLayout( self.tabs, edit=True, tabLabel=( (self.tabMeta, 'Metas'), (self.tabBits, 'Bits'), (self.tabAttrs, 'Attributes'), (self.tabXML, 'XML') ) ) # Show the window. cmds.showWindow( self.winName )
def build_bits_gui( self ): ''' Build the bits GUI sub-layout. ''' # Build bits controls # Primitive buttons. self.sphere_btn = QtGui.QToolButton( self ) self.sphere_btn.setStyleSheet( 'border:0' ) self.sphere_btn.setAutoRaise( True ) self.sphere_btn.setIcon( QtGui.QIcon( ':/riggingUI/icons/bit_sphere.png' ) ) self.sphere_btn.setIconSize( QtCore.QSize(32,32) ) self.sphere_btn.setText( 'Sphere' ) self.sphere_btn.clicked.connect( self.primitive_buttons ) self.box_btn = QtGui.QToolButton( self ) self.box_btn.setStyleSheet( 'border:0' ) self.box_btn.setAutoRaise( True ) self.box_btn.setIcon( QtGui.QIcon( ':/riggingUI/icons/bit_box.png' ) ) self.box_btn.setIconSize( QtCore.QSize(32,32) ) self.box_btn.setText( 'Box' ) self.box_btn.clicked.connect( self.primitive_buttons ) self.cylinder_btn = QtGui.QToolButton( self ) self.cylinder_btn.setStyleSheet( 'border:0' ) self.cylinder_btn.setAutoRaise( True ) self.cylinder_btn.setIcon( QtGui.QIcon( ':/riggingUI/icons/bit_cylinder.png' ) ) self.cylinder_btn.setIconSize( QtCore.QSize(32,32) ) self.cylinder_btn.setText( 'Cylinder' ) self.cylinder_btn.clicked.connect( self.primitive_buttons ) self.cone_btn = QtGui.QToolButton( self ) self.cone_btn.setStyleSheet( 'border:0' ) self.cone_btn.setAutoRaise( True ) self.cone_btn.setIcon( QtGui.QIcon( ':/riggingUI/icons/bit_cone.png' ) ) self.cone_btn.setIconSize( QtCore.QSize(32,32) ) self.cone_btn.setText( 'Cone' ) self.cone_btn.clicked.connect( self.primitive_buttons ) self.torus_btn = QtGui.QToolButton( self ) self.torus_btn.setStyleSheet( 'border:0' ) self.torus_btn.setAutoRaise( True ) self.torus_btn.setIcon( QtGui.QIcon( ':/riggingUI/icons/bit_torus.png' ) ) self.torus_btn.setIconSize( QtCore.QSize(32,32) ) self.torus_btn.setText( 'Torus' ) self.torus_btn.clicked.connect( self.primitive_buttons ) # Bit tools. self.match_translation_btn = QtGui.QPushButton( 'Match Translation' ) self.match_translation_btn.setIcon( QtGui.QIcon( ':/riggingUI/icons/icon_match_translation.png' ) ) self.match_translation_btn.setIconSize( QtCore.QSize(16,16) ) self.match_translation_btn.setStyleSheet( 'text-align: left; padding: 4px' ) self.match_translation_btn.clicked.connect( lambda a='tran':TransformUtility.matchTransforms( a ) ) self.match_rotation_btn = QtGui.QPushButton( 'Match Rotation' ) self.match_rotation_btn.setIcon( QtGui.QIcon( ':/riggingUI/icons/icon_match_rotation.png' ) ) self.match_rotation_btn.setIconSize( QtCore.QSize(16,16) ) self.match_rotation_btn.setStyleSheet( 'text-align: left; padding: 4px' ) self.match_rotation_btn.clicked.connect( lambda a='rot':TransformUtility.matchTransforms( a ) ) self.match_all_btn = QtGui.QPushButton( 'Match All' ) self.match_all_btn.setIcon( QtGui.QIcon( ':/riggingUI/icons/icon_match_all.png' ) ) self.match_all_btn.setIconSize( QtCore.QSize(16,16) ) self.match_all_btn.setStyleSheet( 'text-align: left; padding: 4px' ) self.match_all_btn.clicked.connect( lambda a='all':TransformUtility.matchTransforms( a ) ) self.copy_bit_settings_btn = QtGui.QPushButton( 'Copy Bit Settings' ) self.copy_bit_settings_btn.setIcon( QtGui.QIcon( ':/riggingUI/icons/bit_copy_settings.png' ) ) self.copy_bit_settings_btn.setIconSize( QtCore.QSize(16,16) ) self.copy_bit_settings_btn.setStyleSheet( 'text-align: left; padding: 4px' ) self.copy_bit_settings_btn.clicked.connect( lambda:FrameUtility.copyBitSettings() ) self.add_child_btn = QtGui.QPushButton( 'Add Child' ) self.add_child_btn.setIcon( QtGui.QIcon( ':/riggingUI/icons/bit_add_child.png' ) ) self.add_child_btn.setIconSize( QtCore.QSize(16,16) ) self.add_child_btn.setStyleSheet( 'text-align: left; padding: 4px' ) self.add_child_btn.clicked.connect( lambda:FrameUtility.setBitChild() ) self.delete_child_btn = QtGui.QPushButton( 'Delete Child' ) self.delete_child_btn.setIcon( QtGui.QIcon( ':/riggingUI/icons/bit_delete_child.png' ) ) self.delete_child_btn.setIconSize( QtCore.QSize(16,16) ) self.delete_child_btn.setStyleSheet( 'text-align: left; padding: 4px' ) self.delete_child_btn.clicked.connect( lambda:FrameUtility.deleteBitChild() ) # Build bits layout. # Primitive buttons bit_primitives_header = QtGui.QLabel() bit_primitives_header.setText( 'Bit Primitives' ) bit_primitives_header.setAlignment( QtCore.Qt.AlignCenter ) bit_primitives_header.setStyleSheet( 'font:bold; font-size:14px; background-color:#2B2B30' ) primitive_frame = QtGui.QFrame() primitive_frame.setFrameShadow( QtGui.QFrame.Sunken ) primitive_frame.setFrameShape( QtGui.QFrame.Box ) primitive_frame.setLineWidth( 1 ) #self.primitive_groupbox.setStyleSheet( 'border:4px; border-style:outset' ) primitive_layout = QtGui.QHBoxLayout() primitive_layout.addWidget( self.sphere_btn ) primitive_layout.addWidget( self.box_btn ) primitive_layout.addWidget( self.cylinder_btn ) primitive_layout.addWidget( self.cone_btn ) primitive_layout.addWidget( self.torus_btn ) primitive_frame.setLayout( primitive_layout ) # Bit tools. bit_tools_header = QtGui.QLabel() bit_tools_header.setText( 'Bit Tools' ) bit_tools_header.setAlignment( QtCore.Qt.AlignCenter ) bit_tools_header.setStyleSheet( 'font:bold; font-size:14px; background-color:#2B2B30' ) bit_tools_grid = QtGui.QGridLayout() bit_tools_grid.setColumnMinimumWidth( 0, 100 ) bit_tools_grid.setColumnMinimumWidth( 1, 100 ) bit_tools_grid.setColumnMinimumWidth( 2, 100 ) bit_tools_grid.setSpacing( 2 ) bit_tools_grid.setContentsMargins( 0,0,0,0 ) # widget, row, col bit_tools_grid.addWidget( self.match_translation_btn, 0, 0 ) bit_tools_grid.addWidget( self.match_rotation_btn, 0, 1 ) bit_tools_grid.addWidget( self.match_all_btn, 0, 2 ) bit_tools_grid.addWidget( self.copy_bit_settings_btn, 1, 0 ) bit_tools_grid.addWidget( self.add_child_btn, 1, 1 ) bit_tools_grid.addWidget( self.delete_child_btn, 1, 2 ) # Added the bits widgets to the sub-layout of the main window. self.sub_layout.addWidget( bit_primitives_header ) self.sub_layout.addWidget( primitive_frame ) self.sub_layout.addWidget( bit_tools_header ) self.sub_layout.addLayout( bit_tools_grid )
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),
def __init__( self ): super( UIBitsTools, self ).__init__() layout = QtGui.QVBoxLayout( self ) # Build bits controls # Presets moduleRootBtn = QTWidgets.imageButton( 'Create Module', ':/riggingUI/icons/preset_module.png', [32,32] ) moduleRootBtn.clicked.connect( lambda a=1:self.preset_buttons(a) ) characterRootBtn = QTWidgets.imageButton( 'Create Character', ':/riggingUI/icons/preset_character.png', [32,32] ) characterRootBtn.clicked.connect( lambda a=2:self.preset_buttons(a) ) # Primitive buttons. sphereBtn = QTWidgets.imageButton( 'Sphere', ':/riggingUI/icons/bit_sphere.png', [32,32] ) sphereBtn.clicked.connect( self.primitive_buttons ) boxBtn = QTWidgets.imageButton( 'Box', ':/riggingUI/icons/bit_box.png', [32,32] ) boxBtn.clicked.connect( self.primitive_buttons ) cylinderBtn = QTWidgets.imageButton( 'Cylinder', ':/riggingUI/icons/bit_cylinder.png', [32,32] ) cylinderBtn.clicked.connect( self.primitive_buttons ) coneBtn = QTWidgets.imageButton( 'Cone', ':/riggingUI/icons/bit_cone.png', [32,32] ) coneBtn.clicked.connect( self.primitive_buttons ) torusBtn = QTWidgets.imageButton( 'Torus', ':/riggingUI/icons/bit_torus.png', [32,32] ) torusBtn.clicked.connect( self.primitive_buttons ) # Bit tools. matchTranslationBtn = QTWidgets.imageTextButton( 'Match Translation', ':/riggingUI/icons/icon_match_translation.png', [16,16] ) matchTranslationBtn.clicked.connect( lambda a='tran':TransformUtility.matchTransforms( a ) ) matchRotationBtn = QTWidgets.imageTextButton( 'Match Rotation', ':/riggingUI/icons/icon_match_rotation.png', [16,16] ) matchRotationBtn.clicked.connect( lambda a='rot':TransformUtility.matchTransforms( a ) ) matchAllBtn = QTWidgets.imageTextButton( 'Match All', ':/riggingUI/icons/icon_match_all.png', [16,16] ) matchAllBtn.clicked.connect( lambda a='all':TransformUtility.matchTransforms( a ) ) copyBitSettingsBtn = QTWidgets.imageTextButton( 'Copy Bit Settings', ':/riggingUI/icons/bit_copy_settings.png', [16,16] ) copyBitSettingsBtn.clicked.connect( lambda:NodeUtility.copyBitSettings() ) addChildBtn = QTWidgets.imageTextButton( 'Add Child', ':/riggingUI/icons/bit_add_child.png', [16,16] ) addChildBtn.clicked.connect( lambda:NodeUtility.setBitChild() ) deleteChildBtn = QTWidgets.imageTextButton( 'Delete Child', ':/riggingUI/icons/bit_delete_child.png', [16,16] ) deleteChildBtn.clicked.connect( lambda:NodeUtility.deleteBitChild() ) # Build bits layout. # Presets. presetsHeader = QTWidgets.basicLabel( 'Bit Presets', 'bold', 14, 'white', '2B2B30' ) presetsHeader.setMinimumHeight( 30 ) presetsHeader.setAlignment( QtCore.Qt.AlignCenter ) presetsFrame = QTWidgets.basicFrame() presetsLayout = QtGui.QHBoxLayout() presetsLayout.addWidget( moduleRootBtn ) presetsLayout.addWidget( characterRootBtn ) presetsFrame.setLayout( presetsLayout ) # Primitive buttons bitPrimitivesHeader = QTWidgets.basicLabel( 'Bit Primitives', 'bold', 14, 'white', '2B2B30' ) bitPrimitivesHeader.setMinimumHeight( 30 ) bitPrimitivesHeader.setAlignment( QtCore.Qt.AlignCenter ) primitiveFrame = QTWidgets.basicFrame() primitiveLayout = QtGui.QHBoxLayout() primitiveLayout.addWidget( sphereBtn ) primitiveLayout.addWidget( boxBtn ) primitiveLayout.addWidget( cylinderBtn ) primitiveLayout.addWidget( coneBtn ) primitiveLayout.addWidget( torusBtn ) primitiveFrame.setLayout( primitiveLayout ) # Bit tools. bitToolsHeader = QTWidgets.basicLabel( 'Bit Tools', 'bold', 14, 'white', '2B2B30' ) bitToolsHeader.setMinimumHeight( 30 ) bitToolsHeader.setAlignment( QtCore.Qt.AlignCenter ) bitToolsGrid = QtGui.QGridLayout() bitToolsGrid.setColumnMinimumWidth( 0, 100 ) bitToolsGrid.setColumnMinimumWidth( 1, 100 ) bitToolsGrid.setColumnMinimumWidth( 2, 100 ) bitToolsGrid.setSpacing( 2 ) bitToolsGrid.setContentsMargins( 0,0,0,0 ) # widget, row, col bitToolsGrid.addWidget( matchTranslationBtn, 0, 0 ) bitToolsGrid.addWidget( matchRotationBtn, 0, 1 ) bitToolsGrid.addWidget( matchAllBtn, 0, 2 ) bitToolsGrid.addWidget( copyBitSettingsBtn, 1, 0 ) bitToolsGrid.addWidget( addChildBtn, 1, 1 ) bitToolsGrid.addWidget( deleteChildBtn, 1, 2 ) # Added the bits widgets to the sub-layout of the main window. layout.addWidget( presetsHeader ) layout.addWidget( presetsFrame ) layout.addWidget( bitPrimitivesHeader ) layout.addWidget( primitiveFrame ) layout.addWidget( bitToolsHeader ) layout.addLayout( bitToolsGrid )