Exemple #1
2
def lcObj_exportObjs(*args, **kwargs):
  ''' Export .obj files from selected geometry, either as one combined file or as individual files per object.  Will recognize and convert poly smooth preview to geometry for export '''
  global prefix
  path = pm.textField(prefix+'_textField_export_path', query=True, text=True)
  objPrefix = pm.textField(prefix+'_textField_prefix', query=True, text=True)
  if objPrefix:
    objPrefix+='_'

  if path:

    sel = pm.ls(sl=True)

    if sel:
      sel = geometry.filterForGeometry(sel)
      print sel

      #undo is the easiest way to work on geometry temporarily
      pm.undoInfo(openChunk=True)

      if pm.checkBox(prefix+'_checkBox_use_smooth', query=True, v=True):
        for obj in sel:
          pm.select(obj)
          #find the objects currently displayed as smooth and create converted poly copies
          if pm.displaySmoothness(q=True, polygonObject=True)[0] == 3:
            pm.mel.performSmoothMeshPreviewToPolygon()

      if pm.checkBox(prefix+'_checkBox_export_indi', query=True, v=True):
        #export objects individually
        for obj in sel:
          pm.select(obj)
          name = str(obj)
          exportString = path+'/'+objPrefix+name+'.obj'
          pm.exportSelected(exportString, force=True, options='groups=1;ptgroups=1;materials=0;smoothing=1;normals=1', type='OBJexport', pr=True, es=True)

      else:
        #export as one object
        pm.select(sel)
        name = ''
        while name == '':
          dialog = pm.promptDialog(title='OBJ Name', message='Enter Name:', button=['OK', 'Cancel'], defaultButton='OK', cancelButton='Cancel', dismissString='Cancel')
          if dialog == 'OK':
            name = pm.promptDialog(query=True, text=True)
            if name:
              exportString = path+'/'+objPrefix+name+'.obj'
              pm.exportSelected(exportString, force=True, options='groups=1;ptgroups=1;materials=0;smoothing=1;normals=1', type='OBJexport', pr=True, es=True)
            else:
              pm.warning("You didn't type a name for your obj")
          if dialog == 'Cancel':
            break

      pm.undoInfo(closeChunk=True)
      pm.undo()
      pm.select(clear=True)

  else:
    pm.warning('Did you specify a path?')
 def testChunkUndo(self):
     @chunk_undo
     def spam():
         pmc.joint(), pmc.joint()
     spam()
     self.assertEqual(len(pmc.ls(type='joint')), 2)
     pmc.undo()
     self.assertFalse(pmc.ls(type='joint'))
def safeRename(objs, newNames):
    '''
    Safely renames the given PyNodes to the given names.

    First validates the names, then renames each node to a name that
    will not conflict with any new name.  If an error is encountered,
    the original name is restored.
    '''

    objPairs = zip(objs, newNames)

    # Validate names
    skipPairs = set([])
    for objPair in objPairs:
        obj, name = objPair
        # Don't try to rename nodes to the same names.
        if name == obj.nodeName(stripNamespace=True):
            skipPairs.add(objPair)
        elif not pm.mel.isValidObjectName(name):
            raise InvalidNameError(
                'Cannot rename "%s" to "%s"' % (obj.nodeName(), name))

    try:
        with gat.internal.UndoChunk():
            # Rename objects to something that I hope doesn't already exist,
            # so that we don't run into issues trying to rename an object in
            # our list to the name of an object that hasn't yet been
            # renamed.

            for objPair in objPairs:
                if objPair in skipPairs:
                    continue

                obj, name = objPair
                try:
                    obj.rename('_' * 80)
                except RuntimeError:
                    print 'Failed to rename %s to %s.  Skipping node.' % (obj, name)
                    skipPairs.add(objPair)

            # Rename things for real
            for objPair in objPairs:
                if objPair not in skipPairs:
                    obj, name = objPair
                    obj.rename(name)

    except RuntimeError as err:
        # Undo bad renames and show error
        pm.undo()
        raise RenameError('Failed while renaming %s to %s: %s' % (obj, name, err.message))
Exemple #4
0
	def move_Up(self):
		cur_item = self.ui.attr_listView.selectedItems()[0].text()
		cur_index = self.attr_List.index(cur_item)
		self.attr_List[cur_index] =  self.attr_List[cur_index - 1]
		self.attr_List[cur_index - 1] = cur_item
		self.ui.attr_listView.clear()
		for each in self.attr_List:
			lock = pm.getAttr(self.ui.object_name.text() +'.'+ each, l = True)
			pm.setAttr(self.ui.object_name.text() +'.'+ each, l = False)
			pm.deleteAttr(self.ui.object_name.text() +'.'+ each)
			pm.undo()
			pm.setAttr(self.ui.object_name.text() +'.'+ each, l = lock)

		self.ui.attr_listView.addItems(self.attr_List)
		self.ui.attr_listView.setCurrentRow( cur_index - 1 )
Exemple #5
0
    def export(self):
        output_path = self.Output_Path.text()
        if not os.path.exists(output_path):
            self.Output_Path.setText("")
            msg = u"路径不存在"
            QtWidgets.QMessageBox.warning(self, u"警告", msg)
            return

        base_name = os.path.basename(output_path)

        sel_list = pm.ls(sl=1)
        if not sel_list:
            msg = u"请选择一个物体"
            QtWidgets.QMessageBox.warning(self, u"警告", msg)
            return
        for sel in sel_list:
            pm.undoInfo(ock=1)

            pm.parent(sel, w=1)
            # NOTE 居中轴心
            pm.xform(sel, cp=1)

            pm.mel.BakeCustomPivot()
            sel.t.set(0, 0, 0)
            sel.r.set(0, 0, 0)

            x, _, z = pm.xform(sel, q=1, rp=1)
            bbox = pm.exactWorldBoundingBox(sel)
            pm.xform(sel, piv=[x, bbox[1], z])
            sel.t.set(0, -bbox[1], 0)
            pm.makeIdentity(apply=1, t=1, r=1, s=1, n=0, pn=0)

            index = 1
            path = os.path.join(output_path,
                                "%s_%s.ma" % (base_name, str(index).zfill(2)))
            while os.path.exists(path):
                index += 1
                path = os.path.join(
                    output_path, "%s_%s.ma" % (base_name, str(index).zfill(2)))

            path = path.replace('\\', '/')
            print(path)
            # commnad = 'FBXExport -f "%s.fbx" -s ' % path.replace('\\','/')
            # NOTE 导出 ma 文件
            pm.mel.file(path, f=1, options="v=0;", typ="mayaAscii", pr=1, es=1)
            pm.undoInfo(cck=1)

            pm.undo()
def findLengthFromParam(crv, param):
    '''
    MFnNurbsCurve has findParamFromLength, but not the other way!
    workaround is to cut the curve at param,
    then get the whole length of the new curve
    '''
    firstCrv, secondCrv, node = pm.detachCurve(crv.u[param], ch=True, rpo=False)
    try:
        length = firstCrv.length()
        pm.undo()
        return length
    except RuntimeError as e:
        print e
        print 'param may be 0'
        pm.undo()
        return 0
    def Down_Right(self, ui):
        listIndex = ui.TargetList.currentIndex()
        itemName = str(listIndex.data())
        selected = pm.select(itemName)
        joint = pm.ls(sl=True)[0]
        pm.undo()

        temp = targetTree[listIndex.row()]
        targetTree[listIndex.row()] = targetTree[listIndex.row() + 1]
        targetTree[listIndex.row() + 1] = temp

        tempIndex = targetIndex[listIndex.row()]
        targetIndex[listIndex.row()] = targetIndex[listIndex.row() + 1]
        targetIndex[listIndex.row() + 1] = tempIndex

        self.updateTargetList(ui, targetTree)
    def __init__(self):
        super(DockableWindow, self).__init__()

        self.shown = False

        # Build our *.ui files into qt/resources, so the subclass can load its layout.
        qt_helpers.compile_all_layouts()

        # How do we make our window handle global hotkeys?
        undo = Qt.QAction('Undo', self)
        undo.setShortcut(Qt.Qt.CTRL + Qt.Qt.Key_Z)
        undo.triggered.connect(lambda: pm.undo())
        self.addAction(undo)

        redo = Qt.QAction('Redo', self)
        redo.setShortcut(Qt.Qt.CTRL + Qt.Qt.Key_Y)
        redo.triggered.connect(lambda: pm.redo(redo=True))
        self.addAction(redo)

        style = ''
        # Maya's checkbox style makes the checkbox invisible when it's deselected,
        # which makes it impossible to tell that there's even a checkbox there to
        # click.  Adjust the background color to fix this.
        style += 'QTreeView::indicator:unchecked { background-color: #000; }'

        # Make tree and list view items slightly larger by default.
        style += 'QTreeView::item { height: 20px; }'
        style += 'QListView::item { height: 26px; }'
        self.setStyleSheet(self.styleSheet() + style)
Exemple #9
0
def up_down_attribute(up=False, down=False):
    """

    Args:
        up: Set the selected attribute go up 1 index in the main channel box
        down: Set the selected attribute go down 1 index in the main channel box

    Returns: Relocation of selected attribute in main channel box

    """
    selections = pm.ls(sl=True)
    if len(selections) != 1:
        return om.MGlobal.displayError("This function only work with one object per time")

    selection = selections[0]

    selected_attr = pm.channelBox("mainChannelBox", query=True, selectedMainAttributes=True)
    list_attr = pm.listAttr(selection, userDefined=True, locked=True)

    if len(list_attr) > 0:
        for attr in list_attr:
            pm.setAttr("{0}.{1}".format(selection, attr), lock=False)

    if down:
        if len(selected_attr) > 1:
            selected_attr.reverse()
            sort = selected_attr
        if len(selected_attr) == 1:
            sort = selected_attr
        for i in sort:
            attr_list = pm.listAttr(selection, userDefined=True)
            attr_list_size = len(attr_list)
            attr_position = attr_list.index(i)
            pm.deleteAttr(selection, attribute=attr_list[attr_position])
            pm.undo()

            for x in range(attr_position + 2, attr_list_size, 1):
                pm.deleteAttr(selection, attribute=attr_list[x])
                pm.undo()

    if up:
        for i in selected_attr:
            attr_list = pm.listAttr(selection, userDefined=True)
            attr_list_size = len(attr_list)
            attr_position = attr_list.index(i)
            if attr_list[attr_position - 1]:
                pm.deleteAttr(selection, attribute=attr_list[attr_position - 1])
                pm.undo()
            for x in range(attr_position + 1, attr_list_size, 1):
                pm.deleteAttr(selection, attribute=attr_list[x])
                pm.undo()

    if len(list_attr) > 0:
        for attr in list_attr:
            pm.setAttr("{0}.{1}".format(selection, attr), lock=True)

    sys.stdout.write("Complete.\n")
Exemple #10
0
def undo_chunk(auto_undo=False, exc_callback=None):
    '''
    Undo chunk context manager...
    '''

    try:
        pm.undoInfo(openChunk=True)
        yield
    except Exception as e:
        pm.undoInfo(closeChunk=True)
        if auto_undo:
            pm.undo()
        if exc_callback:
            exc_callback(e)
        raise
    else:
        pm.undoInfo(closeChunk=True)
 def inner(*args, **kwargs):
     err = None
     pmc.undoInfo(openChunk=True)
     try:
         res = func(*args, **kwargs)
     except Exception as err:
         raise
     finally:
         pmc.undoInfo(closeChunk=True) # Close undo!
         if err: # Did we error out?
             pmc.undo()
             e_type, e_name, e_trace = sys.exc_info() # Last error
             pmc.confirmDialog(
                 t="Uh oh... %s" % e_type.__name__,
                 m=str(e_name)
                 )
     return res
Exemple #12
0
def deleteAttr(up=False, tmp=False):
    objs = pm.ls(sl=True)
    attrs = pm.channelBox("mainChannelBox", q=True, sma=True)
    sl_attrs = copy.deepcopy(attrs)
    
    for obj in objs:
        if up:
            attrs = pm.listAttr(obj, ud=True)
            for attr in sl_attrs:
                attrs.remove(attr)
        for attr in attrs:
            try:
                pm.deleteAttr (obj, at=attr)
                if tmp:
                    pm.undo()
            except:
                pass
    def R_Down(self, ui):
        index = ui.TargetList.currentIndex()
        itemText = str(index.data())

        selected = pm.select(itemText)
        selectedJoint = pm.ls(sl=True)[0]
        pm.undo()

        temp = targetTree[index.row()]
        targetTree[index.row()] = targetTree[index.row() + 1]
        targetTree[index.row() + 1] = temp

        tempIndex = targetIndex[index.row()]
        targetIndex[index.row()] = targetIndex[index.row() + 1]
        targetIndex[index.row() + 1] = tempIndex

        self.updateTargetList(ui, targetTree)
def amcveProfile(cvSrc, trim):
	"""
	"""
	cvSrc = pm.ls(cvSrc)[0]
	tiLen = []

	if trim:
		tiLen.append(pm.playbackOptions(q= 1, min= 1))
		tiLen.append(pm.playbackOptions(q= 1, max= 1))
		pm.undoInfo(ock= 1)
		pm.setKeyframe(cvSrc, insert= 1, t= tiLen, f= tiLen)
		pm.undoInfo(cck= 1)

	cvBaseMod = {
			'cvTyp' : pm.objectType(cvSrc),
			'prInf' : cvSrc.getPreInfinityType().key,
			'poInf' : cvSrc.getPostInfinityType().key,
			'weedT' : pm.keyTangent(cvSrc, q= 1, weightedTangents= 1),
			'breaD' : pm.keyframe(cvSrc, q= 1, breakdown= 1)
	}
	cvPortray = {
			'Frame' : pm.keyframe(cvSrc, q= 1, timeChange= 1),
			'Float' : pm.keyframe(cvSrc, q= 1, floatChange= 1),
			'Value' : pm.keyframe(cvSrc, q= 1, valueChange= 1)
	}
	cvFeature = {
			'TLock' : pm.keyTangent(cvSrc, q= 1, lock= 1),
			'WLock' : pm.keyTangent(cvSrc, q= 1, weightLock= 1),
			'InTyp' : pm.keyTangent(cvSrc, q= 1, inTangentType= 1),
			'OuTyp' : pm.keyTangent(cvSrc, q= 1, outTangentType= 1),
			'InWet' : pm.keyTangent(cvSrc, q= 1, inWeight= 1),
			'OuWet' : pm.keyTangent(cvSrc, q= 1, outWeight= 1),
			'InAng' : pm.keyTangent(cvSrc, q= 1, inAngle= 1),
			'OuAng' : pm.keyTangent(cvSrc, q= 1, outAngle= 1)
	}
	cvSrcProfile = {
			'cvTrimmed' : tiLen,
			'cvBaseMod' : cvBaseMod,
			'cvPortray' : cvPortray,
			'cvFeature' : cvFeature
	}
	if trim:
		pm.undo()

	return cvSrcProfile
def findLengthFromParam(crv, param):
    '''
    MFnNurbsCurve has findParamFromLength, but not the other way!
    workaround is to cut the curve at param,
    then get the whole length of the new curve
    '''
    firstCrv, secondCrv, node = pm.detachCurve(crv.u[param],
                                               ch=True,
                                               rpo=False)
    try:
        length = firstCrv.length()
        pm.undo()
        return length
    except RuntimeError as e:
        print e
        print 'param may be 0'
        pm.undo()
        return 0
Exemple #16
0
def exportAssetAssembly(name, rigTopNode, meshTopNode, path, postScript=None):
    if pm.ls(rigTopNode):
        rigTopNode = pm.PyNode(rigTopNode)
    else:
        pm.displayError(
            "{} doesn't exist or duplicated. Please check your "
            "scene".format(rigTopNode))
        return

    if pm.ls(meshTopNode):
        meshTopNode = pm.PyNode(meshTopNode)
    else:
        pm.displayError(
            "{} doesn't exist or duplicated. Please check "
            "your scene".format(meshTopNode))
        return
    # check the folder and script
    # if the target name exist abort and request another name

    deformer_jnts = rigTopNode.rigGroups[3].connections()[0].members()
    if not deformer_jnts:
        pm.displayError(
            "{} is empty. The tool can't find any joint".format(meshTopNode))

    # export connections and cut joint connections

    # cut al possible remaining connection and adjust hierarchy

    # pot script
    if postScript:
        try:
            execfile(postScript)
        except Exception as ex:
            template = "An exception of type {0} occured. Arguments:\n{1!r}"
            message = template.format(type(ex).__name__, ex.args)
            pm.displayError(message)
            cont = pm.confirmBox("FAIL: Script Fail",
                                 "Do you want to export anyway?" + "\n\n" +
                                 message + "\n\n" + traceback.format_exc(),
                                 "Continue", "Cancel")
            if not cont:
                pm.undo()
                return
Exemple #17
0
def exportRig(path=None):
    """
    Exports a rig from the current scene.
    This command relies on our static root joint existing in the scene.
    
    Args:
        path(str): A destination fbx file path.
    
    Returns:
        str: The exported file path.
    """
    # path = path or saveFbxDialog('Export Rig Dialog')
    path = path or os.path.join(getSceneCharacterAssetDirectory(), 'skeleton.fbx')

    # Find the root and bounding box
    root = getRootJoint()
    if root is None:
        raise RootJointException('Export rig failed, could not find a root joint in the scene.')
    box = getBoundingBox()

    try:
        pmc.undoInfo(openChunk=True)
        if root.getParent() is not None:
            pmc.parent(root, world=True)
        if box.getParent() is not None:
            pmc.parent(box, world=True)

        # Disconnect all connections and constraints
        for joint in [root] + getBindSkeleton():
            joint.message.disconnect(outputs=True)
            constraints = joint.getChildren(type='constraint')
            if len(constraints) > 0:
                pmc.delete(constraints)

        exportFbx([root, box], path, animation=False)
    finally:
        pmc.undoInfo(closeChunk=True)
        if not pmc.undoInfo(uqe=True, q=True):
            pmc.undo()

    # Convert to hkx
    ckcmd.importrig(path, os.path.dirname(path))
Exemple #18
0
def randomizer_createUserInterface():
	"""--------------------------------------------------------------------------
	Create User Interface Procedure
	--------------------------------------------------------------------------"""
	

	pm.window('randomizer_window', s=0, rtf=0, t="randomizer", wh=(300, 700))
	# Create UI elements
	pm.columnLayout('mainColumnLayout', h=900, w=248, columnAlign="center", adjustableColumn=1)
	pm.separator('selectedTransformObjectsSeparator', h=10, w=240, st="none")
	pm.text('selectedTransformObjectsText', fn="boldLabelFont", h=24, l="selected transform Objects", w=240, al="center")
	pm.textScrollList('selectedTransformObjectsTextScrollList', h=80, w=240)
	pm.button('loadObjectsButton', h=28, c=lambda *args: randomizer_loadSelection(0), l="load transform Objects", w=240)
	pm.separator('selectedMaterialsSeparator', h=10, w=240, st="none")
	pm.text('selectedMaterialsText', fn="boldLabelFont", h=24, l="selected Materials", w=240, al="center")
	pm.textScrollList('selectedMaterialsTextScrollList', h=80, w=240)
	pm.button('loadMaterialsButton', h=28, c=lambda *args: randomizer_loadSelection(1), l="load Materials", w=240)
	pm.separator('transformAttributesSeparator', h=10, w=240, st="none")
	pm.text('randomizeAttributesText', fn="boldLabelFont", h=24, l="randomize Attributes", w=240, al="center")
	pm.checkBoxGrp('randomizeAttributesCheckBoxGrp', h=24, l4="Material", l2="Rotate", l3="Scale", w=240, l1="Translate", ncb=4, cw=[(1, 67), (2, 57), (3, 50), (4, 57)])
	pm.separator('translateAttributesSeparator', h=10, w=240, st="none")
	pm.text('translateText', fn="boldLabelFont", h=24, l="Translate", w=240, al="center")
	pm.floatFieldGrp('minMaxXtranslateFloatFieldGrp', pre=3, el="max X", bgc=(0.25, 0, 0), h=24, l="min X", nf=2, v1=0, v2=0, w=240, cw=[(1, 60), (2, 60), (3, 60), (4, 60)])
	pm.floatFieldGrp('minMaxYtranslateFloatFieldGrp', pre=3, el="max Y", bgc=(0, 0.25, 0), h=24, l="min Y", nf=2, v1=0, v2=0, w=240, cw=[(1, 60), (2, 60), (3, 60), (4, 60)])
	pm.floatFieldGrp('minMaxZtranslateFloatFieldGrp', pre=3, el="max Z", bgc=(0, 0, 0.25), h=24, l="min Z", nf=2, v1=0, v2=0, w=240, cw=[(1, 60), (2, 60), (3, 60), (4, 60)])
	pm.separator('rotateAttributesSeparator', h=10, w=240, st="none")
	pm.text('rotateText', fn="boldLabelFont", h=24, l="Rotate", w=240, al="center")
	pm.floatFieldGrp('minMaxXrotateFloatFieldGrp', pre=3, el="max X", bgc=(0.25, 0, 0), h=24, l="min X", nf=2, v1=0, v2=0, w=240, cw=[(1, 60), (2, 60), (3, 60), (4, 60)])
	pm.floatFieldGrp('minMaxYrotateFloatFieldGrp', pre=3, el="max Y", bgc=(0, 0.25, 0), h=24, l="min Y", nf=2, v1=0, v2=0, w=240, cw=[(1, 60), (2, 60), (3, 60), (4, 60)])
	pm.floatFieldGrp('minMaxZrotateFloatFieldGrp', pre=3, el="max Z", bgc=(0, 0, 0.25), h=24, l="min Z", nf=2, v1=0, v2=0, w=240, cw=[(1, 60), (2, 60), (3, 60), (4, 60)])
	pm.separator('scaleAttributesSeparator', h=10, w=240, st="none")
	pm.text('scaleText', fn="boldLabelFont", h=24, l="Scale", w=240, al="center")
	pm.floatFieldGrp('minMaxXscaleFloatFieldGrp', pre=3, el="max X", bgc=(0.25, 0, 0), h=24, l="min X", nf=2, v1=1, v2=1, w=240, cw=[(1, 60), (2, 60), (3, 60), (4, 60)])
	pm.floatFieldGrp('minMaxYscaleFloatFieldGrp', pre=3, el="max Y", bgc=(0, 0.25, 0), h=24, l="min Y", nf=2, v1=1, v2=1, w=240, cw=[(1, 60), (2, 60), (3, 60), (4, 60)])
	pm.floatFieldGrp('minMaxZscaleFloatFieldGrp', pre=3, el="max Z", bgc=(0, 0, 0.25), h=24, l="min Z", nf=2, v1=1, v2=1, w=240, cw=[(1, 60), (2, 60), (3, 60), (4, 60)])
	pm.separator('randomizeSelectionSeparator', h=10, w=240, st="none")
	pm.button('randomizeAbsoluteButton', h=28, c=lambda *args: randomizer_randomizeSelection(), l="randomize Abolute", w=240)
	pm.button('randomizeRelativeButton', h=28, c=lambda *args: randomizer_randomizeSelection(relative=True), l="randomize Relative", w=240)
	pm.separator('timeAttributesSeparator', h=10, w=240, st="none")
	pm.text('timeText', fn="boldLabelFont", h=24, l="Time", w=240, al="center")
	pm.intFieldGrp('minMaxTimeIntFieldGrp', el="max", bgc=(0, 0, 0), h=24, l="min", nf=2, v1=-1, v2=1, w=240, cw=[(1, 60), (2, 60), (3, 60), (4, 60)])
	pm.button('setUniformKeyframe', h=28, c=lambda *args: rand_Keyframe(objects=None, attribute="all", axis=["X", "Y", "Z"], uniform=True, min=-10, max=10, step=1), l="Set Keyframes uniform", w=240)
	pm.button('setRandomKeyframe', h=28, c=lambda *args: rand_Keyframe(objects=None, attribute="all", axis=["X", "Y", "Z"], uniform=False, min=-10, max=10, step=1), l="Set Keyframes random", w=240)
	pm.separator('undoSeparator', h=10, w=240, st="none")
	pm.button('undoButton', h=28, c=lambda *args: pm.undo(), l="undo", w=240)
	pm.iconTextButton('staschiIconTextButton', h=28, c=lambda *args: randomizer_loadHelpWebsite(), l="www.staschi.com", w=240, st="textOnly")

	pm.setParent('..')
	pm.setParent('..')
	# Display UI
	pm.showWindow('randomizer_window')
Exemple #19
0
def main():
    
    sel_list = pm.ls(sl=1)
    if not sel_list:
        return
    sel = sel_list[0]
    
    pm.undoInfo(ock=1)

    pm.parent(sel,w=1)
    # NOTE 居中轴心
    pm.xform(sel,cp=1)
    
    pm.mel.BakeCustomPivot()
    
    sel.t.set(0,0,0)
    sel.r.set(0,0,0)
    x,_,z = pm.xform(sel,q=1,rp=1)
    bbox = pm.exactWorldBoundingBox(sel)
    pm.xform(sel,piv=[x,bbox[1],z])
    
    pm.mel.BakeCustomPivot()
    pm.xform(sel,ws=1,t=[0,0,0])
    index = 1
    path = os.path.join(output_path,"%s_%s.ma" % (base_name,str(index).zfill(2)))
    while os.path.exists(path):
        index += 1
        path = os.path.join(output_path,"%s_%s.ma" % (base_name,str(index).zfill(2)))

    path = path.replace('\\','/')
    print(path)
    # commnad = 'FBXExport -f "%s.fbx" -s ' % path.replace('\\','/')
    # NOTE 导出 ma 文件
    pm.mel.file(path,f=1,options="v=0;",typ="mayaAscii",pr=1,es=1)
    pm.undoInfo(cck=1)
    
    pm.undo()
Exemple #20
0
def exportAssetAssembly(name, rigTopNode, meshTopNode, path, postScript=None):
    """Export the asset assembly. Model, rig and connections dict.

    Args:
        name (str): Name of the asset
        rigTopNode (str): Name of the rig top node
        meshTopNode (str): Name of the model top node
        path (str): Pestination directory
        postScript (path, optional): Script to run before export

    Returns:
        None: None
    """
    if pm.ls(rigTopNode):
        rigTopNode = pm.PyNode(rigTopNode)
    else:
        pm.displayError(
            "{} doesn't exist or duplicated. Please check your "
            "scene".format(rigTopNode))
        return

    if pm.ls(meshTopNode):
        meshTopNode = pm.PyNode(meshTopNode)
    else:
        pm.displayError(
            "{} doesn't exist or duplicated. Please check "
            "your scene".format(meshTopNode))
        return
    # check the folder and script
    # if the target name exist abort and request another name

    deformer_jnts = rigTopNode.rigGroups[3].connections()[0].members()
    if not deformer_jnts:
        pm.displayError(
            "{} is empty. The tool can't find any joint".format(meshTopNode))

    # export connections and cut joint connections
    file_path = os.path.join(path, name + ".jmm")
    dm_nodes = exportConnections(source=deformer_jnts,
                                 filePath=file_path,
                                 disc=True)

    # cut al possible remaining connection and adjust hierarchy
    # joint or visibility
    jnt_org = pm.PyNode("jnt_org")
    pm.disconnectAttr(rigTopNode.jnt_vis, jnt_org.visibility)

    # restructure model
    model = pm.createNode("transform",
                          n="model",
                          p=None,
                          ss=True)
    pm.addAttr(model, ln="rigGroups", at='message', m=1)
    pm.parent(meshTopNode, jnt_org, model)

    # disconnect jnt set
    sets = rigTopNode.listConnections(type="objectSet")

    deformersGrp = None
    for oSet in sets:
        if "deformers_grp" in oSet.name():
            deformersGrp = oSet

    if deformersGrp:
        for cnx in deformersGrp.message.listConnections(p=True):
            pm.disconnectAttr(deformersGrp.message, cnx)
        pm.connectAttr(deformersGrp.message, model.attr("rigGroups[0]"))

    # disconnect bindPoses
    dg_poses = rigTopNode.message.listConnections(type="dagPose", p=True)
    for dgp in dg_poses:
        if dgp.node().name().startswith("bindPose"):
            pm.disconnectAttr(rigTopNode.message, dgp)

    # post script
    if postScript:
        try:
            execfile(postScript)
        except Exception as ex:
            template = "An exception of type {0} occured. Arguments:\n{1!r}"
            message = template.format(type(ex).__name__, ex.args)
            pm.displayError(message)
            cont = pm.confirmBox("FAIL: Script Fail",
                                 "Do you want to export anyway?" + "\n\n"
                                 + message + "\n\n" + traceback.format_exc(),
                                 "Continue", "Cancel")
            if not cont:
                pm.undo()
                return

    # export rig model
    pm.select(dm_nodes, r=True)
    pm.select(rigTopNode, add=True)
    file_path = os.path.join(path, name + "_rig.ma")
    exp = pm.exportSelected(file_path, f=True, type="mayaAscii")
    pm.displayInfo(exp)

    # export mesh and joints
    pm.select(model, r=True)
    file_path = os.path.join(path, name + "_model.ma")
    exp = pm.exportSelected(file_path, f=True, type="mayaAscii")
    pm.displayInfo(exp)
Exemple #21
0
 def __exit__(self, exc_type, exc_val, exc_tb):
     pmc.undoInfo(closeChunk=True)
     # Undo in case of an exception being raised
     if exc_val is not None:
         pmc.undo()
Exemple #22
0
	def exportFullPackage(self, palName, version, bake= False, anim= False):
		"""
		Export Palettes, Descriptions, Grooming, Guides, all together,
		even bake modifiers befoer export if needed.
		"""
		self.clearPreview()
		
		# bake modifiers
		generator = {}
		if bake:
			for desc in xg.descriptions(palName):
				# bake Noise modifiers
				# fxModules evals from bottom to top
				clumpModLast = ''
				for fxm in xg.fxModules(palName, desc):
					if xg.fxModuleType(palName, desc, fxm) == 'ClumpingFXModule':
						# set the top clumpingMod cvAttr to True, for anim modifiers which needs clump
						if clumpModLast:
							xg.setAttr('cvAttr', 'false', palName, desc, clumpModLast)
						xg.setAttr('cvAttr', 'true', palName, desc, fxm)
						clumpModLast = fxm
					if xg.fxModuleType(palName, desc, fxm) == 'NoiseFXModule':
						# temporarily turn off lod so we dont bake it in
						lod = xg.getAttr('lodFlag', palName, desc)
						xg.setAttr('lodFlag', 'false', palName, desc)
						# change mode for bake
						xg.setAttr('mode', '2', palName, desc, fxm)
						# bake the noise
						pm.mel.xgmNullRender(pb= desc)
						# restore
						xg.setAttr('lodFlag', lod, palName, desc)
						# change mode to baked
						xg.setAttr('mode', '1', palName, desc, fxm)
				# bake groom modifiers
				fxm = xg.addFXModule(palName, desc, 'BakedGroomManagerFXModule')
				xg.setAttr('active', 'true', palName, desc, fxm)
				xg.bakedGroomManagerBake(palName, desc)
				# set Generator to XPD
				generator[desc] = xg.getActive(palName, desc, 'Generator')
				xg.setActive(palName, desc, 'FileGenerator')
		
		# change to export version path and keep current
		workPath = xg.getAttr('xgDataPath', palName)
		workProj = xg.getAttr('xgProjectPath', palName)
		xg.setAttr('xgDataPath', self.paletteVerDir(palName, version, raw= True), palName)
		xg.setAttr('xgProjectPath', self.projPath, palName)
		# get resolved repo path
		dataPath = self.paletteVerDir(palName, version)

		# set [xgDogTag] attr for ANIM record branchName
		if anim:
			xg.setAttr('xgDogTag', version, palName)

		# export descriptions
		for desc in xg.descriptions(palName):
			dstDescDir = xg.expandFilepath('${DESC}', desc, True, True)
			expPath = dstDescDir + desc + '.xdsc'
			xg.exportDescription(palName, desc, expPath)
			# copy map files
			srcDescVar = workPath.replace('${PROJECT}', workProj) + '/${DESC}'
			srcDescDir = xg.expandFilepath(srcDescVar, desc)
			for mapDir in os.listdir(srcDescDir):
				srcMap = os.path.join(srcDescDir, mapDir)
				dstMap = os.path.join(dstDescDir, mapDir)
				if os.path.isdir(srcMap):
					dir_util.copy_tree(srcMap, dstMap)

		# export palettes
		expPath = dataPath + '/' + palName + '.xgen'
		xg.exportPalette(palName, expPath)

		# export grooming
		for desc in xg.descriptions(palName):
			igdesc = xg.getAttr('groom', palName, desc)
			if igdesc:
				expPath = xg.expandFilepath('${DESC}/groom', desc, True, True)
				tpu = 5
				sampling = 1
				igDescr = xg.igDescription(desc)
				# export Attribute Map
				try:
					pm.waitCursor(state= True)
					# may have .ptx file handle lock issue
					pm.mel.iGroom(exportMaps= expPath, texelsPerUnit= tpu,
						instanceMethod= sampling, description= igDescr)
				finally:
					pm.waitCursor(state= False)
				# export Mask
				try:
					pm.waitCursor(state= True)
					# may have .ptx file handle lock issue
					pm.mel.iGroom(exportMask= expPath, texelsPerUnit= tpu,
						description= igDescr)
				finally:
					pm.waitCursor(state= False)
				# export Region
				try:
					pm.waitCursor(state= True)
					# may have .ptx file handle lock issue
					pm.mel.iGroom(exportRegion= expPath, texelsPerUnit= tpu,
						description= igDescr)
				finally:
					pm.waitCursor(state= False)
				# export Settings
				jsonPath = expPath + 'groomSettings.json'
				groomSettings = {}.fromkeys(['density', 'length', 'width'])
				for key in groomSettings:
					groomSettings[key] = pm.getAttr(igdesc + '.' + key)
				with open(jsonPath, 'w') as jsonFile:
					json.dump(groomSettings, jsonFile, indent=4)

		# export guides
		with undoable('exportGuides'):
			for desc in xg.descriptions(palName):
				# listGuides
				guides = xg.descriptionGuides(desc)
				if not guides:
					continue
				expPath = xg.expandFilepath('${DESC}', desc)
				pm.select(guides, r= 1)
				# guides to curves
				curves = pm.mel.xgmCreateCurvesFromGuides(0, True)
				# export as alembic
				if not pm.pluginInfo('AbcExport', q= 1, l= 1):
					pm.loadPlugin('AbcExport')
				abcCmds = '-frameRange 1 1 -uvWrite -worldSpace -dataFormat ogawa '
				abcRoot = '-root ' + ' -root '.join([cur.longName() for cur in pm.ls(curves)])
				abcPath = expPath + 'curves.abc'
				pm.mel.AbcExport(j= abcCmds + abcRoot + ' -file ' + abcPath)
		pm.undo()

		if anim:
			# save out hairSystem preset
			presetMel = []
			for nodeType in ['nucleus', 'hairSystem', 'nRigid']:
				presetDict = self.ioAttrPreset(nodeType, True)
				presetMel.extend(presetDict.values())
			# move preset file to version repo
			presetRepo = self.nDynPresetPath(palName, version)
			if not os.path.exists(presetRepo):
				os.mkdir(presetRepo)
			for prs in presetMel:
				dstPath = '/'.join([presetRepo, os.path.basename(prs)])
				shutil.move(prs, dstPath)
			# create empty _shot_ folder
			shotDir = self.paletteDeltaDir(palName, version, '')
			if not os.path.exists(shotDir):
				os.mkdir(shotDir)

		# export snapshot
		for i in range(5):
			tmpPath = self.snapshotTmp % (i+1)
			if os.path.isfile(tmpPath):
				imgPath = self.snapshotImgPath(palName, version, str(i+1))
				if not os.path.exists(os.path.dirname(imgPath)):
					os.mkdir(os.path.dirname(imgPath))
				shutil.move(tmpPath, imgPath)

		# restore dataPath
		xg.setAttr('xgDataPath', workPath, palName)
		xg.setAttr('xgProjectPath', workProj, palName)

		# restore modifiers
		if bake:
			for desc in xg.descriptions(palName):
				# bake Noise modifiers
				for fxm in xg.fxModules(palName, desc):
					if xg.fxModuleType(palName, desc, fxm) == 'NoiseFXModule':
						# restore to live mode
						xg.setAttr('mode', '0', palName, desc, fxm)
				# remove bake groom modifiers
				for fxm in xg.fxModules(palName, desc):
					if xg.fxModuleType(palName, desc, fxm) == 'BakedGroomManagerFXModule':
						xg.removeFXModule(palName, desc, fxm)
				# restore Generator
				xg.setActive(palName, desc, generator[desc])

		self.refresh('Full')

		self.notifyMsg('Collection Export Complete !', 0)

		return True
Exemple #23
0
def exportSkin(meshes=None, path=None):
    """
    Exports the given mesh nodes as a skyrim skin fbx.
    If no meshes are given the current selected meshes will be used. If no meshes are selected all meshes skinned
    to the root skeleton will be used.
    
    Args:
        meshes(list): A list of meshes to export. 
        path(str): The destination fbx path. 

    Returns:
        str: The exported file path.
    """
    path = path or saveFbxDialog('Save Skin Dialog', dir=getSceneCharacterAssetDirectory())

    # Get the root skeleton
    root = getRootJoint()
    if root is None:
        raise RootJointException('Export rig failed, could not find a root joint in the scene.')
    rootSkeleton = [root] + root.listRelatives(ad=True, type='joint')

    def getSkinnedMeshes():
        clusters = set()
        for joint in rootSkeleton:
            for cluster in pmc.ls(pmc.listConnections(joint), type='skinCluster'):
                clusters.add(cluster)
        return [pmc.skinCluster(cluster, geometry=True, q=True)[0] for cluster in clusters]

    meshes = meshes or pmc.selected() or getSkinnedMeshes()
    meshes = getMeshes(meshes)

    if len(meshes) > 1:
        raise NotImplementedError('Multiple meshes selected for export. Currently we only support one mesh per skin.')

    # Check max influences
    for mesh in meshes:
        if not _checkMaxInfluences(mesh):
            raise MaxInfluenceException('Failed to export "%s". Skinning contains more than 4 influences.' % mesh)

    try:
        pmc.undoInfo(openChunk=True)

        # Set vertex colors to white
        for mesh in meshes:
            pmc.polyColorPerVertex(mesh, colorRGB=[1, 1, 1], a=1)

        # To fix certain issues with skinning we need to mess with the normals
        for mesh in meshes:
            pmc.bakePartialHistory(mesh, prePostDeformers=True)  # Delete Non-deformer history
            pmc.polyNormalPerVertex(mesh, unFreezeNormal=True)  # Unlock the normals
            pmc.polySoftEdge(mesh, a=180)  # Soften the normals
            pmc.bakePartialHistory(mesh, prePostDeformers=True)  # Delete Non-deformer history
            pmc.polyNormalPerVertex(mesh, freezeNormal=True)  # Lock the normals
            pmc.polySoftEdge(mesh, a=0)  # Harden the normals
            pmc.bakePartialHistory(mesh, prePostDeformers=True)  # Delete Non-deformer history

        # Remove all joint constraints
        constraints = root.listRelatives(ad=True, type='constraint')
        if len(constraints) > 0:
            pmc.delete(constraints)

        # Disconnect message connections
        for joint in rootSkeleton:
            joint.message.disconnect()
            if not joint.hasAttr(MATCH_ATTR_NAME):
                continue
            for input in joint.attr(MATCH_ATTR_NAME).inputs(plugs=True):
                input.disconnect(joint.attr(MATCH_ATTR_NAME))

        exportFbx(rootSkeleton + [mesh.getParent() for mesh in meshes], path=path)

    finally:
        pmc.undoInfo(closeChunk=True)
        pmc.undo()

    # Export nif
    ckcmd.importskin(path, os.path.dirname(path))
 def testUndoChunk(self):
     with undo_chunk():
         pmc.joint(), pmc.joint()
     self.assertEqual(len(pmc.ls(type='joint')), 2)
     pmc.undo()
     self.assertFalse(pmc.ls(type='joint'))
Exemple #25
0
def subDelAttr(obj, string):
    pm.deleteAttr(obj, at=string)
    pm.undo()
Exemple #26
0
def lcObj_exportObjs(*args, **kwargs):
    ''' Export .obj files from selected geometry, either as one combined file or as individual files per object.  Will recognize and convert poly smooth preview to geometry for export '''
    global prefix
    path = pm.textField(prefix + '_textField_export_path',
                        query=True,
                        text=True)
    objPrefix = pm.textField(prefix + '_textField_prefix',
                             query=True,
                             text=True)
    if objPrefix:
        objPrefix += '_'

    if path:

        sel = pm.ls(sl=True)

        if sel:
            sel = geometry.filterForGeometry(sel)
            print sel

            #undo is the easiest way to work on geometry temporarily
            pm.undoInfo(openChunk=True)

            if pm.checkBox(prefix + '_checkBox_use_smooth', query=True,
                           v=True):
                for obj in sel:
                    pm.select(obj)
                    #find the objects currently displayed as smooth and create converted poly copies
                    if pm.displaySmoothness(q=True,
                                            polygonObject=True)[0] == 3:
                        pm.mel.performSmoothMeshPreviewToPolygon()

            if pm.checkBox(prefix + '_checkBox_export_indi',
                           query=True,
                           v=True):
                #export objects individually
                for obj in sel:
                    pm.select(obj)
                    name = str(obj)
                    exportString = path + '/' + objPrefix + name + '.obj'
                    pm.exportSelected(
                        exportString,
                        force=True,
                        options=
                        'groups=1;ptgroups=1;materials=0;smoothing=1;normals=1',
                        type='OBJexport',
                        pr=True,
                        es=True)

            else:
                #export as one object
                pm.select(sel)
                name = ''
                while name == '':
                    dialog = pm.promptDialog(title='OBJ Name',
                                             message='Enter Name:',
                                             button=['OK', 'Cancel'],
                                             defaultButton='OK',
                                             cancelButton='Cancel',
                                             dismissString='Cancel')
                    if dialog == 'OK':
                        name = pm.promptDialog(query=True, text=True)
                        if name:
                            exportString = path + '/' + objPrefix + name + '.obj'
                            pm.exportSelected(
                                exportString,
                                force=True,
                                options=
                                'groups=1;ptgroups=1;materials=0;smoothing=1;normals=1',
                                type='OBJexport',
                                pr=True,
                                es=True)
                        else:
                            pm.warning("You didn't type a name for your obj")
                    if dialog == 'Cancel':
                        break

            pm.undoInfo(closeChunk=True)
            pm.undo()
            pm.select(clear=True)

    else:
        pm.warning('Did you specify a path?')
Exemple #27
0
def export_anim(root):

    # Select Root
    pymel.select(root)

    scene_name = str(pymel.sceneName().basename().split('.')[0])
    path = os.path.join(siteCustomize.ROOT_DIR, 'animations', 'export',
                        scene_name)
    path = path.replace('\\', '/')
    pymel.mel.eval('FBXResetExport()')

    pymel.mel.eval('FBXExportInAscii -v true')

    # EXPORT
    pymel.mel.eval('FBXExport -f "{0}" -s'.format(path))


if __name__ == '__main__':
    #
    # ctrl = pymel.selected()[0]
    #
    # export_pose(ctrl.region, pose_name='test')

    with pymel.UndoChunk():
        main = pymel.PyNode('Main_Net')
        root = main.jnts[0]
        bake_anim(root)
        export_anim(root)

    pymel.undo()
Exemple #28
0
def lcObj_exportObjs(*args, **kwargs):
    ''' Export .obj files from selected geometry, either as one combined file or as individual files per object.  Will recognize and convert poly smooth preview to geometry for export '''
    global lct_cfg
    global prefix
    global defaultPath

    path = pm.textField(prefix+'_textField_export_path', query=True, text=True)
    objPrefix = pm.textField(prefix+'_textField_prefix', query=True, text=True)
    if objPrefix:
        objPrefix+='_'

    if path and path != defaultPath:

        sel = pm.ls(sl=True)

        if sel:
            sel = lcGeometry.Geometry.filterForGeometry(sel)
            #undo is the easiest way to work on geometry temporarily
            pm.undoInfo(openChunk=True)

            if sel:

                if pm.checkBox(prefix+'_checkBox_use_smooth', query=True, v=True):
                    for obj in sel:
                        pm.select(obj)
                        #find the objects currently displayed as smooth and create converted poly copies
                        if pm.displaySmoothness(q=True, polygonObject=True)[0] == 3:
                            pm.mel.performSmoothMeshPreviewToPolygon()

                if pm.checkBox(prefix+'_checkBox_export_indi', query=True, v=True):
                    #export objects individually
                    for obj in sel:
                        pm.select(obj)
                        nameSplit = str(obj).split('|')
                        if len(nameSplit) > 1:
                            name = nameSplit[-1]
                        else:
                            name = nameSplit[0]
                        exportString = os.path.normpath(os.path.join(path,str(objPrefix+name+'.obj')))
                        try:
                            pm.exportSelected(exportString, force=True, options='groups=1;ptgroups=1;materials=0;smoothing=1;normals=1', type='OBJexport', pr=True, es=True)
                            lcUtility.Utility.lc_print('Exporting: {0}'.format(exportString))
                        except:
                            lcUtility.Utility.lc_print_exception('Failed to export: {0}'.format(exportString))
                    #undo export individually
                    pm.undoInfo(closeChunk=True)
                    pm.undo()

                else:
                    #export as one object
                    pm.select(sel)
                    name = ''
                    while name == '':
                        dialog = pm.promptDialog(title='OBJ Name', message='Enter Name:', button=['OK', 'Cancel'], defaultButton='OK', cancelButton='Cancel', dismissString='Cancel')
                        if dialog == 'OK':
                            name = pm.promptDialog(query=True, text=True)
                            if name:
                                exportString = os.path.normpath(os.path.join(path,str(objPrefix+name+'.obj')))
                                try:
                                    pm.exportSelected(exportString, force=True, options='groups=1;ptgroups=1;materials=0;smoothing=1;normals=1', type='OBJexport', pr=True, es=True)
                                    pm.undoInfo(closeChunk=True)
                                    pm.undo()
                                    lcUtility.Utility.lc_print('Exporting: {0}'.format(exportString))
                                except:
                                    pm.undoInfo(closeChunk=True)
                                    pm.undo()
                                    lcUtility.Utility.lc_print('Failed to export: {0}'.format(exportString), mode='warning')
                            else:
                                pm.undoInfo(closeChunk=True)
                                pm.undo()
                                lcUtility.Utility.lc_print("You didn't type a name for your obj", mode='warning')
                        if dialog == 'Cancel':
                            pm.undoInfo(closeChunk=True)
                            pm.undo()
                            break

                pm.select(sel)

            else:
                lcUtility.Utility.lc_print('Select a mesh first', mode='warning')
        else:
            lcUtility.Utility.lc_print('Select a mesh first', mode='warning')
    else:
        lcUtility.Utility.lc_print('Did you set a path?', mode='warning')
Exemple #29
0
		# save out presets
		presetDict = {}
		for node in pm.ls(type= nodeType):
			presetName = node.name()
			if save:
				pm.nodePreset(save= [node, presetName])
			else:
				pm.nodePreset(load= [node, presetName])
			presetDict[node.name()] = presetVar % (nodeType, presetName)

		return presetDict



@contextmanager
def undoable(name):
	pm.undoInfo(ock=True, cn=name)

	try:
		yield name
	except Exception, e:
		import traceback
		pm.warning('[XGen Hub] : Error while running undoable <%s> : %s' % (name, e))
		traceback.print_exc()
	finally:
		pm.undoInfo(cck=True)
		try:
			pm.undo()
		except RuntimeError as e:
			pm.warning(str(e))
Exemple #30
0
 def __exit__(self, exc_type, exc_val, exc_tb):
     pmc.undoInfo(closeChunk=True)
     if exc_val is not None:
         pmc.undo()
 def testUndoChunk(self):
     with undo_chunk():
         pmc.joint(), pmc.joint()
     self.assertEqual(len(pmc.ls(type='joint')), 2)
     pmc.undo()
     self.assertFalse(pmc.ls(type='joint'))
Exemple #32
0
 def __exit__(self, exc_type, exc_val, exc_tb):
     pmc.undoInfo(closeChunk=True)
     if exc_val is not None:
         pmc.undo()
Exemple #33
0
    def __init__(self):
        super(KeyingWindow, self).__init__()

        # How do we make our window handle global hotkeys?
        undo = Qt.QAction('Undo', self)
        undo.setShortcut(Qt.Qt.CTRL + Qt.Qt.Key_Z)
        undo.triggered.connect(lambda: pm.undo())
        self.addAction(undo)

        redo = Qt.QAction('Redo', self)
        redo.setShortcut(Qt.Qt.CTRL + Qt.Qt.Key_Y)
        redo.triggered.connect(lambda: pm.redo(redo=True))
        self.addAction(redo)

        self.weight_node = None
        self.shown = False
        self.callback_ids = om.MCallbackIdArray()

        self._currently_refreshing = False

        style = r'''
        /* Maya's checkbox style makes the checkbox invisible when it's deselected,
         * which makes it impossible to tell that there's even a checkbox there to
         * click.  Adjust the background color to fix this. */
        QTreeView::indicator:unchecked {
            background-color: #000;
        }
        '''
        self.setStyleSheet(style)

        self.time_change_listener = maya_helpers.TimeChangeListener(self._time_changed, pause_during_playback=False)

        # Make sure zMouthController has been generated.
        qt_helpers.compile_all_layouts()

        from zMayaTools.qt_widgets import draggable_progress_bar
        reload(draggable_progress_bar)

        from zMayaTools.qt_generated import zMouthController
        reload(zMouthController)

        self.ui = zMouthController.Ui_zMouthController()
        self.ui.setupUi(self)

        self.ui.selectionBar.setMinimum(0)
        self.ui.selectionBar.setMaximum(1000)
        self.ui.mainWeightBar.setMinimum(0)
        self.ui.mainWeightBar.setMaximum(1000)

        self.ui.selectNodeButton.clicked.connect(self.select_current_node)
        self.ui.shapeSelection1.currentIndexChanged.connect(self.shape1Changed)
        self.ui.shapeSelection2.currentIndexChanged.connect(self.shape2Changed)
        self.ui.selectedNodeDropdown.currentIndexChanged.connect(self.selectedNodeChanged)
        self.ui.setKeyShape1.clicked.connect(self.clicked_key_shape_1)
        self.ui.setKeyShape2.clicked.connect(self.clicked_key_shape_2)
        self.ui.keySelection.clicked.connect(self.clicked_key_selection)
        self.ui.keyMainWeight.clicked.connect(self.clicked_key_main_weight)
        self.ui.soloShape1.clicked.connect(self.solo_shape1)
        self.ui.soloShape2.clicked.connect(self.solo_shape2)
        self.ui.selectionBar.mouse_movement.connect(self.set_selection_bar_value)
        self.ui.mainWeightBar.mouse_movement.connect(self.set_main_weight)

        self.ui.selectionBar.set_undo_chunk_around_dragging('Dragging selection')
        self.ui.mainWeightBar.set_undo_chunk_around_dragging('Dragging weight')

        # This will call selectedNodeChanged, and trigger the rest of the refresh.
        self.refresh_weight_node_list()