def undoIt(self): cmds.undoInfo( swf=0 ) for attr, data in self.__undoSetList: cmds.setAttr( attr, data, type='matrix' ) for skinNode in self.__skinNodes: cmds.dgdirty( skinNode ) cmds.undoInfo( swf=1 )
def assign( source, target, rangemode, replacemode ) : ''' Assign a marker, copying from source to destination :param source: the source marker to copy data from :param target: the target marker to paste data on to :param replacemode: 'swap' or 'extract' :param rangemode: sett getSourceRange ''' print "Assign: %s ---> %s Modes: %s/%s" % (source, target, rangemode, replacemode ) if not m.objExists( target ) : print "renaming: " + source + " as " + target m.rename( source, target) return True if rangemode == 'gap' : # fill the gap in the target using keys from the source s = curve.currentSegmentOrGap( target, datarate.nodeRate(source) ) if s is None or s[0] != 'gap' : print "Skipping: " + str(source) + " (not currently in a gap)" return # values of surrounding keyframes sourceIn, sourceOut = s[1] # contract range sourceIn = sourceIn + 0.5 sourceOut = sourceOut - 0.5 else : sourceIn, sourceOut = getSourceRange( source, rangemode ) # expand to sourceIn = sourceIn - 0.5 sourceOut = sourceOut + 0.5 print "In: %f Out: %f" % (sourceIn, sourceOut) if replacemode == 'swap' : keyTools.swap( (source,target), sourceIn, sourceOut ) if replacemode == 'extract' : # copy the segment over, any clashing keys on the marker will be removed as unlabelled keyTools.extractRange( target, sourceIn, sourceOut ) m.cutKey( source, t = ( sourceIn, sourceOut ) ) m.pasteKey( target, option='replace' ) keyTools.setActiveKeys( source, delete=True ) keyTools.setActiveKeys( target ) #m.select(target) m.dgdirty(a=True)
def redoIt(self): picked = OpenMaya.MObjectArray() dependNode = OpenMaya.MObject() # Selected dependency node # Create a selection list iterator OpenMaya.MGlobal.getActiveSelectionList(self.__sList) iter = OpenMaya.MItSelectionList(self.__sList) # Iterate over all selected dependency nodes # and save them in a list while not iter.isDone(): # Get the selected dependency node iter.getDependNode(dependNode) picked.append(dependNode) iter.next() self.__undoSetList = [] self.__skinNodes = [] cmds.undoInfo( swf=0 ) try: for i in range( picked.length() ): fnPicked = OpenMaya.MFnDagNode( picked[i] ) hists = cmds.listHistory( fnPicked.fullPathName() ) skinNode = None for hist in hists: if cmds.nodeType( hist ) == 'skinCluster': skinNode = hist break if not skinNode: continue fnSkinNode = OpenMaya.MFnDependencyNode( self.__getMObject( skinNode ) ) plugGeomMatrix = fnSkinNode.findPlug( 'geomMatrix' ) plugMatrix = fnSkinNode.findPlug( 'matrix' ) plugBindPre = fnSkinNode.findPlug( 'bindPreMatrix' ) for i in range( plugMatrix.numElements() ): loIndex = plugMatrix[i].logicalIndex() srcJoints = cmds.listConnections( plugMatrix[i].name(), s=1, d=0 ) if not srcJoints: continue undoSet = [plugBindPre.elementByLogicalIndex( loIndex ).name(), cmds.getAttr( plugBindPre.elementByLogicalIndex( loIndex ).name() )] cmds.setAttr( plugBindPre.elementByLogicalIndex( loIndex ).name(), cmds.getAttr( srcJoints[0] +'.wim' ), type='matrix' ) self.__undoSetList.append( undoSet ) self.__undoSetList.append( [plugGeomMatrix.name(), cmds.getAttr( plugGeomMatrix.name() )] ) cmds.setAttr( plugGeomMatrix.name(), cmds.getAttr( fnPicked.fullPathName() + '.wm' ), type='matrix' ) cmds.dgdirty( fnSkinNode.name() ) self.__skinNodes.append( fnSkinNode.name() ) except:pass cmds.undoInfo( swf=1 )
def addNode(self, node): coral.Node.addNode(self, node) if "CoralMayaNode" in node.classNames(): # we have to call updateCoralAttributeMap here because doing so in a CoralMayaNode contructor we would be wrong (the CoralMayaNode wouldn't be under its parent yet). cmds.coralMayaCmd("updateCoralAttributeMap", self._mayaNode) for attr in node.inputAttributes(): if hasattr(attr, "mayaAttribute"): # this will guarantee things are up to date from the start cmds.dgdirty(attr.mayaNode() + "." + attr.mayaAttribute())
def updatePose(control, attribute): """update the pose""" locatorCurveMap = getLocatorCurveMap(control, attribute) locs = [] for locGrp in locatorCurveMap.keys(): locGrpChild = cmds.listRelatives(locGrp, c=1) if not locGrpChild: cmds.warning("cant find control for : " + locGrp) continue locCtrl = locGrpChild[0] loc = cmds.spaceLocator() locs.append(loc[0]) #snap the new locator to the position of the locator control cmds.delete(cmds.pointConstraint(locCtrl, loc)) cmds.delete(cmds.orientConstraint(locCtrl, loc)) #zero out the locator control cmds.setAttr(locCtrl + ".translate", 0, 0, 0) cmds.setAttr(locCtrl + ".rotate", 0, 0, 0) #snap the locator group to the new locator cmds.pointConstraint(loc, locGrp) cmds.orientConstraint(loc, locGrp) #force an evaluation of the scene to make sure that the right values are on the locator group cmds.dgdirty(a=1) attrs = locatorCurveMap[locGrp].keys() for attr in attrs: #get the value value = cmds.getAttr(locGrp + "." + attr) #get the animation curve that drives the locator animCurve = locatorCurveMap[locGrp][attr] #update the set driven key - for now we're always assuming 10 cmds.setKeyframe(animCurve, f=10, v=value) #now delete the locators and force the evaluation cmds.delete(locs) cmds.select(cl=1) cmds.dgdirty(a=1) print "updating pose completed!"
def reset(self,char=''): ''' Reset the orient pivot position within the baseRig hierarchy. @param char: Namespace of the orient pivot to set. @type char: str ''' orient = char+self.orient # set rotate pivot key mc.setAttr(orient+'.rotatePivot',0,0,0) mc.setAttr(orient+'.rotatePivotTranslate',0,0,0) # set pivot keys mc.setKeyframe(orient,at='rotatePivot',) mc.setKeyframe(orient,at='rotatePivotTranslate',) # force update mc.dgdirty(orient)
def set(self,snapTo,char=''): ''' Set the orient pivot position within the baseRig hierarchy. @param snapTo: Object to snap orient pivot to. @type snapTo: str @param char: Namespace of the orient pivot to set. @type char: str ''' orient = char+self.orient # set orient rotate pivot pos = mc.xform(snapTo,q=1,ws=1,rp=1) mc.xform(orient,ws=1,rp=(pos[0],pos[1],pos[2])) # set pivot key mc.setKeyframe(orient,at='rotatePivot') mc.setKeyframe(orient,at='rotatePivotTranslate') # force update mc.dgdirty(orient)
def doAssign( self, source, dest ) : rangemode = self.sourceRangeSelector.currentText() # none, fill, segment, spike, all, selected replacemode = self.replaceModeSelector.currentText() # extract, swap, overwrite # if the node does not exist, just rename the source to being the target if not m.objExists( dest ) : print "Rename " + str( source ) + " for " + str(dest) m.rename( source, dest ) self.draw(refresh=True) m.dgdirty(a=True) return if rangemode == 'fill' : print "Fill: " + source + " for: " + dest cmd = "from " + localsettings.module + " import keyTools as kt;" cmd+= 'kt.fill("%s", "%s")' % (dest, source) m.evalDeferred(cmd) #keyTools.fill( dest, source ) cmd = "from " + localsettings.module + " import labeler;" cmd+= "labeler.INSTANCE.draw();" cmd+= "import maya.cmds as m; m.dgdirty(a=True)" m.evalDeferred(cmd) return # must be eval-ed for undo to work.. cmd = "from " + localsettings.module + " import assign;" cmd+= "assign.assign( '%s', '%s', '%s', '%s');" % ( source, dest, rangemode, replacemode ) print cmd m.evalDeferred(cmd) if self.toolActive: cmd = 'import maya.cmds as m; m.setToolTo("' + self.context + '")' m.evalDeferred(cmd) cmd = "from " + localsettings.module + " import labeler;" cmd+= "labeler.INSTANCE.draw()" m.evalDeferred(cmd)
def removeSpace( self, space ): '''Removes spaces. @param space: Space index you want to delete. @type space: *int* ''' # get current space currentSpace = cmds.getAttr( '%s.%s' % (self.spaceAttrNode,'space') ) # ---------------------------------------------------------------------- # edit enum attribute # get new spaces existingSpaces = cmds.attributeQuery( 'space', node=self.spaceAttrNode, listEnum=True)[0].split(':') if space>len(existingSpaces): raise IndexError, 'No space found in index: %i' % space newSpaces = [existingSpaces[i] for i in range(len(existingSpaces)) if i!=space] # edit attribute cmds.addAttr( '%s.%s' % (self.spaceAttrNode,'space'), e=True, enumName=':'.join(newSpaces) ) # ---------------------------------------------------------------------- # delete group in spacesGrp spaces = cmds.listRelatives( self.spaceGrp, type='transform' ) cmds.delete( spaces[space] ) # ---------------------------------------------------------------------- # re- connect self.__connect__() # ---------------------------------------------------------------------- # refresh if space == currentSpace: cmds.dgdirty( a=True )
def main(name="assembly", position=(0,0,0), radius=1, fbx=False, cog=True, body=True, pelvis=True): if type(position) == str or type(position) == unicode: position = mc.xform(position, q=True, rp=True, ws=True) grp = mc.createNode("transform", n=name) mc.addAttr(grp, ln="joints", at="bool", dv=True, k=True) mc.addAttr(grp, ln="editJoints", at="bool", k=True) if fbx: mc.setAttr(grp+".joints", False) mc.addAttr(grp, ln="fbxJoints", at="bool", dv=True, k=True) mc.addAttr(grp, ln="editFbxJoints", at="bool", k=True) mc.addAttr(grp, ln="controls", at="bool", dv=True, k=True) mc.addAttr(grp, ln="_geometry", at="bool", dv=True, k=True) mc.addAttr(grp, ln="editGeometry", at="bool", k=True) # # controls # ctrl = [] ctrl.append(common.control(name="world", parent=grp, radius=radius*5, color=13, lockAttr=["v"], hideAttr=["v"])[1]) if cog: ctrl.append(common.control(name="cog", parent=ctrl[0], position=position, color=13, radius=radius*4, lockAttr=["s","v"], hideAttr=["sx","sy","sz","v"])[1]) if body: ctrl.append(common.control(name="body", parent=ctrl[1], position=ctrl[1], color=13, radius=radius*3, lockAttr=["s","v"], hideAttr=["sx","sy","sz","v"])[1]) if pelvis: ctrl.append(common.control(name="pelvis", parent=ctrl[2], position=ctrl[2], radius=radius*2, lockAttr=["s","v"], hideAttr=["sx","sy","sz","v"])[1]) grps = [None]*2 rev = mc.createNode("reverse") if fbx: grps[0] = mc.createNode("transform", n="skeleton_fbx") grps[1] = mc.createNode("transform", n="geometry_fbx") mc.connectAttr(grp+".fbxJoints", grps[0]+".v") mc.setAttr(grps[0]+".overrideDisplayType", 2) mc.connectAttr(grp+".editFbxJoints", rev+".inputX") mc.connectAttr(rev+".outputX", grps[0]+".overrideEnabled") mc.createNode("transform", n="constraints_fbx", p=grp) else: grps[1] = mc.createNode("transform", n="geometry", p=grp) mc.connectAttr(grp+"._geometry", grps[1]+".v") mc.connectAttr(grp+".editGeometry", rev+".inputY") mc.connectAttr(rev+".outputY", grps[1]+".overrideEnabled") mc.setAttr(grps[1]+".overrideDisplayType", 2) for n in grps: for a in ["tx","ty","tz","rx","ry","rz","sx","sy","sz","v"]: try: mc.setAttr(n+"."+a, l=True, k=False, cb=False) except: pass # # selection sets # n1 = mc.sets(n="ik_controls_set", em=True) n2 = mc.sets(n="fk_controls_set", em=True) for n in ctrl: mc.connectAttr(n+".message", n2+".dnSetMembers", na=True) n3 = mc.sets(n="joints_set", em=True) n4 = mc.sets(n=name+"_set", em=True) mc.sets(n1, n2, n3, add=n4) mc.select(grp) mc.dgdirty(a=True) return grp
def main(name="hand", side="", control=None, parent=None, positions=None, inheritTemplateRotations=False, radius=1): # create template joints if needed tmp = None if not positions: positions = template(name=name) tmp = copy.deepcopy(positions) cnt = len(positions) if cnt == 0: return # positions from template transforms/joints rotations = {} for i in range(cnt): cnt2 = len(positions[i]) if cnt2 < 3: raise Exception("At least 3 joints are needed to form a finger.") for j in range(cnt2): if type(positions[i][j]) == str or type( positions[i][j]) == unicode: if inheritTemplateRotations: if i not in rotations.viewkeys(): rotations[i] = [None] * cnt2 rotations[i][j] = mc.xform(positions[i][j], q=True, ro=True, ws=True) positions[i][j] = mc.xform(positions[i][j], q=True, rp=True, ws=True) if not control: center = [0, 0, 0] for i in range(cnt): center[0] += positions[i][0][0] center[1] += positions[i][0][1] center[2] += positions[i][0][2] center[0] /= cnt center[1] /= cnt center[2] /= cnt control = common.control(name=name, position=center, normal=(1, 0, 0), color=17, radius=radius * 2, lockAttr=("v"), hideAttr=("v"))[1] parent = control if not mc.objExists(control + ".joints"): mc.addAttr(control, ln="joints", at="bool", dv=True, k=True) if not mc.objExists(control + ".editJoints"): mc.addAttr(control, ln="editJoints", at="bool", dv=True, k=True) if not mc.objExists(control + ".fingerControls"): mc.addAttr(control, ln="fingerControls", at="bool", dv=True, k=True) if not mc.objExists(control + ".bend"): mc.addAttr(control, ln="bend", at="double", min=-10, max=10, k=True) if not mc.objExists(control + ".splay"): mc.addAttr(control, ln="splay", at="double", min=-10, max=10, k=True) md1 = mc.createNode("multiplyDivide") mc.connectAttr(control + ".bend", md1 + ".input1.input1X") mc.connectAttr(control + ".bend", md1 + ".input1.input1Y") mc.connectAttr(control + ".bend", md1 + ".input1.input1Z") mc.setAttr(md1 + ".input2X", 6) mc.setAttr(md1 + ".input2Y", 9) mc.setAttr(md1 + ".input2Z", 9) md2 = mc.createNode("multiplyDivide") mc.connectAttr(control + ".bend", md2 + ".input1.input1X") mc.connectAttr(control + ".bend", md2 + ".input1.input1Y") mc.connectAttr(control + ".bend", md2 + ".input1.input1Z") mc.setAttr(md2 + ".input2X", 8) mc.setAttr(md2 + ".input2Y", 11) mc.setAttr(md2 + ".input2Z", 7.5) jnt = [None] * cnt ctrl_grp = [None] * cnt ctrl = [None] * cnt for i in range(cnt): mc.select(cl=True) cnt2 = len(positions[i]) jnt[i] = [None] * cnt2 if cnt2 == 3: j = 0 else: j = 1 jnt[i][0] = mc.createNode("joint", n="finger_" + side + str(i + 1) + "_jnt" + str(j + 1)) mc.setAttr(jnt[i][0] + ".t", positions[i][j][0], positions[i][j][1], positions[i][j][2]) jnt[i][1] = mc.createNode("joint", n="finger_" + side + str(i + 1) + "_jnt" + str(j + 2)) mc.setAttr(jnt[i][1] + ".t", positions[i][j + 1][0], positions[i][j + 1][1], positions[i][j + 1][2]) jnt[i][2] = mc.createNode("joint", n="finger_" + side + str(i + 1) + "_jnt" + str(j + 3)) mc.setAttr(jnt[i][2] + ".t", positions[i][j + 2][0], positions[i][j + 2][1], positions[i][j + 2][2]) if j: jnt[i][3] = mc.createNode("joint", n="finger_" + side + str(i + 1) + "_jnt1") mc.setAttr(jnt[i][3] + ".t", positions[i][0][0], positions[i][0][1], positions[i][0][2]) c = mc.aimConstraint(jnt[i][0], jnt[i][3], aim=(1, 0, 0), u=(0, 0, 1), wut="objectrotation", wuo=parent)[0] mc.rename(c, jnt[i][3] + "_aimcon") jnt[i][3] = mc.parent(jnt[i][3], parent)[0] mc.setAttr(jnt[i][3] + ".radius", radius * 0.3) mc.connectAttr(control + ".joints", jnt[i][3] + ".v") if not inheritTemplateRotations: n = mc.createNode("transform") mc.delete(mc.pointConstraint(jnt[i][0], jnt[i][2], n)) mc.delete( mc.aimConstraint(jnt[i][2], n, aim=(1, 0, 0), u=(0, 0, 1), wut="object", wuo=jnt[i][1])) mc.delete( mc.aimConstraint(jnt[i][1], jnt[i][0], aim=(1, 0, 0), u=(0, 0, -1), wut="object", wuo=n)) mc.delete( mc.aimConstraint(jnt[i][2], jnt[i][1], aim=(1, 0, 0), u=(0, 0, -1), wut="object", wuo=n)) mc.delete(mc.orientConstraint(jnt[i][1], jnt[i][2])) mc.delete(n) else: for j in range(cnt2): mc.setAttr(jnt[i][j] + ".r", rotations[i][j][0], rotations[i][j][1], rotations[i][j][2]) r = mc.getAttr(jnt[i][0] + ".r")[0] mc.setAttr(jnt[i][0] + ".jo", r[0], r[1], r[2]) mc.setAttr(jnt[i][0] + ".r", 0, 0, 0) r = mc.getAttr(jnt[i][1] + ".r")[0] mc.setAttr(jnt[i][1] + ".jo", r[0], r[1], r[2]) mc.setAttr(jnt[i][1] + ".r", 0, 0, 0) mc.parent(jnt[i][1], jnt[i][0]) r = mc.getAttr(jnt[i][2] + ".r")[0] mc.setAttr(jnt[i][2] + ".jo", r[0], r[1], r[2]) mc.setAttr(jnt[i][2] + ".r", 0, 0, 0) mc.parent(jnt[i][2], jnt[i][1]) ctrl_grp[i] = [None, None, None] ctrl[i] = [None, None, None] for j in range(3): if j: _parent = ctrl[i][j - 1] lockAttr = ("t", "rx", "rz", "s", "v") hideAttr = ("tx", "ty", "tz", "rx", "rz", "sx", "sy", "sz", "v") else: _parent = parent lockAttr = ("s", "v") hideAttr = ("sx", "sy", "sz", "v") ctrl_grp[i][j], ctrl[i][j] = common.control( name="finger_" + side + str(i + 1) + "_fk" + str(j + 1), parent=_parent, position=jnt[i][j], rotation=jnt[i][j], normal=(1, 0, 0), color=13, radius=radius * 0.3, lockAttr=lockAttr, hideAttr=hideAttr, numOffsetGroups=True) mc.connectAttr( control + ".fingerControls", mc.listRelatives(ctrl[i][j], pa=True, s=True)[0] + ".v") jnt[i][j] = mc.parent(jnt[i][j], ctrl[i][j])[0] mc.setAttr(jnt[i][j] + ".radius", radius * 0.3) mc.connectAttr(control + ".joints", jnt[i][j] + ".v") # bend mc.connectAttr(md2 + ".outputX", ctrl_grp[i][0] + ".ray") mc.connectAttr(md2 + ".outputY", ctrl_grp[i][1] + ".ray") mc.connectAttr(md2 + ".outputZ", ctrl_grp[i][2] + ".ray") # splay delta = 3.0 / (cnt * 0.5) for i in range(cnt): md = mc.createNode("multiplyDivide") mc.connectAttr(control + ".splay", md + ".input1.input1X") if mc.xform(ctrl_grp[i][0], q=True, rp=True, ws=True)[0] >= -0.001: mc.setAttr(md + ".input2X", -3 + delta * i) else: mc.setAttr(md + ".input2X", 3 - delta * i) if len(jnt[i]) == 4: mc.connectAttr(md + ".outputX", ctrl_grp[i][0] + ".raz") else: mc.connectAttr( md + ".outputX", mc.listRelatives(ctrl[i][0], pa=True, p=True)[0] + ".raz") # selection sets if side: name += "_" + side common.sets(name, sum(jnt, []), sum(ctrl, []), None) # selectable joints common.selectable(control + ".editJoints", sum(jnt, [])) if tmp: mc.delete(sum(tmp, [])) mc.select(control) mc.dgdirty(a=True) return control
def run_correctness_test(referenceMode, modes, fileName=None, resultsPath=None, verbose=False, maxFrames=CORRECTNESS_MAX_FRAMECOUNT, dataTypes=['matrix', 'vertex', 'screen'], emSetup=CORRECTNESS_NO_SETUP): """ Evaluate the file in multiple modes and compare the results. referenceMode: Mode to which other modes will be compared for correctness. It's a string that can be passed to emModeManager.setMode() function. modes: List of modes to run the tests in. They must be have the following methods: getTitle : returns a string describing the mode getEmMode : returns a string to be passed to emModeManager.setMode() before running the test. getContext : returns a context object that can set extra state on enter and reset it on exit (or None if not needed). fileName: Name of file to load for comparison. None means use the current scene resultsPath: Where to store the results. None means don't store anything verbose: If True then dump the differing values when they are encountered maxFrames: Maximum number of frames in the playback, to avoid long tests. dataTypes: List of data types to include in the analysis. These are the possibilities: matrix: Any attribute that returns a matrix vector: Any attribute with type 3Double vertex: Attributes on the mesh shape that hold vertex positions number: Any attribute that returns a number screen: Screenshot after the animation runs emSetup: What to do before running an EM mode test, in bitfield combinations CORRECTNESS_NO_SETUP Do nothing, just run playback CORRECTNESS_DOUBLE_PLAYBACK Run playback twice to ensure graph is valid CORRECTNESS_INVALIDATE Invalidate the graph to force rebuild CORRECTNESS_LOAD Load the file between every mode's run (Default is to just load once at the beginning.) Returns a list of value tuples indicating the run mode and the number of changes encountered in that mode. e.g. ['ems', 0] If verbose is true then instead of counts return a list of actual changes. e.g. ['ems', ["plug1,oldValue,newValue"]] Changed values are a CSV 3-tuple with "plug name", "value in reference mode", "value in the named test mode" in most cases. In the special case of an image difference the plug name will be one of the special ones below and the values will be those generated by the comparison method used: DGState.SCREENSHOT_PLUG_MD5 : md5 values when the image compare could not be done DGState.SCREENSHOT_PLUG_MAG : md5 and image difference values from ImageMagick DGState.SCREENSHOT_PLUG_IMF : md5 and image difference values from imf_diff """ # Fail if the fileName is not a valid Maya file. if fileName != None and not __is_maya_file(fileName): print 'ERROR: %s is not a Maya file' % fileName return {} # Load the fileName if it was specified, otherwise the current scene will bbbbbbbbb if fileName != None: cmds.file(fileName, force=True, open=True) ref_results = None ref_results_image = None # Using lists allows me to do a comparison of two identical modes. # If resultsPath is given then the second and successive uses of the # same type will go into files with an incrementing suffix (X.ref.txt, # X.ref1.txt, X.ref2.txt...) mode_results_files = [] mode_compare_files = [] mode_results_image_files = [] results = [] em_plug_file_name = None # Create a list of unique mode suffixes, appending a count number whenever # the same mode appears more than once on the modes list. mode_counts = {} unique_modes = [] mode_counts['ref'] = 1 for modeObject in modes: mode = modeObject.getTitle() mode_counts[mode] = mode_counts.get(mode, 0) + 1 suffix = '' if mode_counts[mode] > 1: suffix = str(mode_counts[mode]) unique_modes.append('%s%s' % (mode, suffix)) if resultsPath != None: # Make sure the path exists if not os.path.isdir(resultsPath): os.makedirs(resultsPath) em_plug_file_name = os.path.join(resultsPath, 'EMPlugs.txt') # Build the rest of the paths to the results files. # If no file was given default the results file prefix to "SCENE". if fileName != None: # Absolute paths cannot be appended to the results path. Assume # that in those cases just using the base name is sufficient. if os.path.isabs(fileName): resultsPath = os.path.join(resultsPath, os.path.basename(fileName)) else: resultsPath = os.path.join(resultsPath, fileName) else: resultsPath = os.path.join(resultsPath, 'SCENE') ref_results = '%s.ref.txt' % resultsPath mode_counts['ref'] = 1 for mode in unique_modes: # mode strings can have '/' which are illegal in filenames, replace with '='. mode = mode.replace('/', '=') mode_results_files.append('%s.%s.txt' % (resultsPath, mode)) mode_compare_files.append('%s.DIFF.%s.txt' % (resultsPath, mode)) else: # Still need the file args to pass in to DGState. None = don't output. for _ in modes: mode_results_files.append(None) mode_compare_files.append(None) # If the image comparison was requested figure out where to store the # file. Done separately because even if the files won't be saved the image # comparison needs to dump a file out for comparison. if 'screen' in dataTypes: if resultsPath == None: image_dir = tempfile.gettempdir() if fileName != None: # Absolute paths cannot be appended to the results path. Assume # that in those cases just using the base name is sufficient. if os.path.isabs(fileName): image_dir = os.path.join(image_dir, os.path.basename(fileName)) else: image_dir = os.path.join(image_dir, fileName) else: image_dir = os.path.join(image_dir, 'SCENE') else: image_dir = resultsPath ref_results_image = '%s.ref.png' % image_dir for mode in unique_modes: # mode strings can have '/' which are illegal in filenames, replace with '='. mode = mode.replace('/', '=') mode_results_image_files.append('%s.%s.png' % (image_dir, mode)) else: ref_results_image = None for _ in unique_modes: mode_results_image_files.append(None) # The IK multi-chain solver is known to create inconsistent results so remove # any joints that are being controlled by it from the list being compared. TODO( 'REFACTOR', 'Is this still needed now that we have an evaluator that handles it and disable EM if they are found?', None) ignored_nodes = [] for node in cmds.ls(type='ikHandle'): try: solver_type = None solver_type = cmds.nodeType( cmds.ikHandle(node, query=True, solver=True)) except Exception: pass # Any other kind of IK solver is fine if solver_type != 'ikMCsolver': continue multi_chain_joints = cmds.ikHandle(node, query=True, jointList=True) if multi_chain_joints is not None: ignored_nodes += multi_chain_joints multi_chain_effector = cmds.ikHandle(node, query=True, endEffector=True) if multi_chain_effector is not None: ignored_nodes += [multi_chain_effector] em_plugs = None comparisons = {} TODO( 'FEATURE', 'Could modify the verbose input to allow dumping of JSON instead of CSV', None) comparison_mode = DGState.OUTPUT_CSV # Record the reference evaluation version of the results with emModeManager() as em_mode: em_mode.setMode(referenceMode) with playbackModeManager() as play_mode: # Set to free running but hit every frame play_mode.setOptions(framesPerSecond=0.0, maxPlaybackSpeed=0.0, loop='once') play_mode.setLimitedRange(maxFrames=maxFrames, fromStart=True) # If no model panel is visible the refresh command won't trigger any evaluation if model_panel_visible(): cmds.refresh() else: cmds.dgdirty(allPlugs=True) if (emSetup & CORRECTNESS_DOUBLE_PLAYBACK) != 0: play_mode.playAll() play_mode.playAll() mDG = DGState() mDG.scan_scene(do_eval=(referenceMode == 'dg'), data_types=dataTypes) mDG.store_state(ref_results, ref_results_image) # Walk all of the modes requested and run the tests for them for mode_num in range(len(modes)): test_mode = modes[mode_num] with emModeManager() as test_em_mode: test_em_mode.setMode(test_mode.getEmMode()) extra_context = test_mode.getContext() if not extra_context: extra_context = EmptyContext() with extra_context: if (emSetup & CORRECTNESS_LOAD != 0) and fileName != None: cmds.file(fileName, force=True, open=True) if (emSetup & CORRECTNESS_DOUBLE_PLAYBACK) != 0: play_mode.playAll() if (emSetup & CORRECTNESS_INVALIDATE) != 0: cmds.evaluationManager(invalidate=True) play_mode.playAll() if em_plugs == None: em_plugs = __find_em_plugs(ignored_nodes) mDG.filter_state(em_plugs) if em_plug_file_name: try: em_handle = open(em_plug_file_name, 'w') for (node, plug_list) in em_plugs.iteritems(): em_handle.write('%s\n' % node) for plug in plug_list.keys(): em_handle.write('\t%s\n' % plug) em_handle.close() except Exception, ex: print 'ERROR: Could not write to EM plug file %s: "%s"' % ( em_plug_file_name, str(ex)) mode_state = DGState() # Catch the case when the EM has been disabled due to unsupported areas in the graph. # When that happens the evaluation has to be forced or the values will be wrong. em_still_enabled = cmds.evaluationManager( query=True, mode=True) != 'dg' and cmds.evaluationManager( query=True, enabled=True) mode_state.scan_scene(do_eval=not em_still_enabled, data_types=dataTypes) mode_state.store_state( mode_results_files[mode_num], mode_results_image_files[mode_num]) results.append(mode_state) results[mode_num].filter_state(em_plugs) mode_title = test_mode.getTitle() (comparison, error_count, _) = mDG.compare(results[mode_num], output_mode=comparison_mode) if verbose: comparisons[mode_title] = comparison else: comparisons[mode_title] = error_count if mode_compare_files[mode_num] is not None: with open(mode_compare_files[mode_num], 'w') as compare_file: compare_file.write(str(comparison))
def writeObjCombineCache(path, name, meshList, startFrame, endFrame, pad=4, uvSet='', worldSpace=True, gz=False): """ Write a .obj cache per frame for the specified list of mesh objects. All meshes in the list will be combined to a single cache. @param path: Destination directory path for the cache files. @type path: str @param name: Cache file output name. @type name: str @param meshList: List of mesh objects to write cache for. @type meshList: list @param startFrame: Cache start frame @type startFrame: float @param endFrame: Cache end frame @type endFrame: float @param pad: Frame number padding for file name. @type pad: str @param uvSet: UVSet to export with cache @type uvSet: str @param worldSpace: Export mesh in world space instead of local or object space. @type worldSpace: bool @param gz: Gzip the cache files @type gz: bool """ # Check path if not os.path.isdir(path): os.makedirs(path) # Check mesh list fullMeshList = meshList for mesh in meshList: if not cmds.objExists(mesh): raise Exception('Mesh "' + mesh + '" does not exist!') if not glTools.utils.mesh.isMesh(mesh): raise Exception('Object "' + mesh + '" is not a valid mesh!') # Check UVs uv = False if uvSet: for mesh in meshList: if cmds.polyUVSet(mesh, q=True, auv=True).count(uvSet): uv = True else: print('UVSet "' + uvSet + '" does not exist for mesh "' + mesh + '"!') # Determine Sample Space if worldSpace: sampleSpace = OpenMaya.MSpace.kWorld else: sampleSpace = OpenMaya.MSpace.kObject # Write mesh cache for f in range(startFrame, endFrame + 1): # Update frame cmds.currentTime(f) cmds.dgdirty(a=True) # Check mesh visibility meshList = [mesh for mesh in fullMeshList if cmds.getAttr(mesh + '.v')] if not meshList: continue # ------------------------- # - Open file for writing - # ------------------------- fPad = glTools.utils.stringUtils.stringIndex(f, pad) if gz: filename = path + '/' + name + '.' + fPad + '.obj.gz' print 'Writing ' + filename FILE = gzip.open(filename, "wb") else: filename = path + '/' + name + '.' + fPad + '.obj' print 'Writing ' + filename FILE = open(filename, "w") # Write cache file header FILE.write('g\n') # --------------------- # - Write Vertex Data - # --------------------- # Write raw point data for m in range(len(meshList)): meshFn = glTools.utils.mesh.getMeshFn(meshList[m]) # Vertex Positions vtxArray = OpenMaya.MPointArray() meshFn.getPoints(vtxArray, sampleSpace) for i in range(vtxArray.length()): FILE.write('v ' + str(vtxArray[i].x) + ' ' + str(vtxArray[i].y) + ' ' + str(vtxArray[i].z) + '\n') # Vertex UVs if uvSet: uvSetName = uvSet else: uvSetName = str(cmds.polyUVSet(meshList[m], q=True, cuv=True)[0]) uArray = OpenMaya.MFloatArray() vArray = OpenMaya.MFloatArray() meshFn.getUVs(uArray, vArray, uvSetName) for i in range(uArray.length()): FILE.write('vt ' + str(uArray[i]) + ' ' + str(vArray[i]) + '\n') # Vertex Normals normArray = OpenMaya.MFloatVectorArray() meshFn.getVertexNormals(False, normArray, sampleSpace) for i in range(vtxArray.length()): FILE.write('vn ' + str(vtxArray[i].x) + ' ' + str(vtxArray[i].y) + ' ' + str(vtxArray[i].z) + '\n') # ------------------- # - Write Face Data - # ------------------- # Track per mesh vertex id offsets vertexOffset = 0 uvOffset = 0 # Initialize face vertex array faceVtxArray = OpenMaya.MIntArray() # Build UV Id pointer object uvIdUtil = OpenMaya.MScriptUtil() uvIdUtil.createFromInt(0) uvIdPtr = uvIdUtil.asIntPtr() # Iterate over meshes for m in range(len(meshList)): # Write cache file header grp = meshList[m].replace(':', '_').lower() FILE.write('g ' + grp + '\n') # Get mesh face iterator faceIter = glTools.utils.mesh.getMeshFaceIter(meshList[m]) # Iterate over mesh faces faceIter.reset() while not faceIter.isDone(): # Get face vertices faceIter.getVertices(faceVtxArray) vtxArray = list(faceVtxArray) vtxCount = len(vtxArray) # Build face data string faceData = 'f ' for i in range(vtxCount): # Vertex Id faceData += str(vtxArray[i] + 1 + vertexOffset) faceData += '/' # UV Id try: faceIter.getUVIndex(i, uvIdPtr) except: pass else: faceData += str(OpenMaya.MScriptUtil(uvIdPtr).asInt() + 1 + uvOffset) faceData += '/' # Vertex Normal Id faceData += str(vtxArray[i] + 1 + vertexOffset) faceData += ' ' faceData += '\n' # Write face data FILE.write(faceData) # Iterate to next face faceIter.next() # Update vertex offset vertexOffset += cmds.polyEvaluate(meshList[m], v=True) uvOffset += cmds.polyEvaluate(meshList[m], uv=True, uvs=uvSetName) # ----------------------- # - Finalize cache file - # ----------------------- # Close File FILE.close() # Print result print 'Write OBJ cache completed!'
def writeObjCombineCache(path,name,meshList,startFrame,endFrame,pad=4,uvSet='',worldSpace=True,gz=False): ''' Write a .obj cache per frame for the specified list of mesh objects. All meshes in the list will be combined to a single cache. @param path: Destination directory path for the cache files. @type path: str @param name: Cache file output name. @type name: str @param meshList: List of mesh objects to write cache for. @type meshList: list @param startFrame: Cache start frame @type startFrame: float @param endFrame: Cache end frame @type endFrame: float @param pad: Frame number padding for file name. @type pad: str @param uvSet: UVSet to export with cache @type uvSet: str @param worldSpace: Export mesh in world space instead of local or object space. @type worldSpace: bool @param gz: Gzip the cache files @type gz: bool ''' # Check path if not os.path.isdir(path): os.makedirs(path) # Check mesh list fullMeshList = meshList for mesh in meshList: if not mc.objExists(mesh): raise Exception('Mesh "'+mesh+'" does not exist!') if not glTools.utils.mesh.isMesh(mesh): raise Exception('Object "'+mesh+'" is not a valid mesh!') # Check UVs uv = False if uvSet: for mesh in meshList: if mc.polyUVSet(mesh,q=True,auv=True).count(uvSet): uv = True else: print('UVSet "'+uvSet+'" does not exist for mesh "'+mesh+'"!') # Determine Sample Space if worldSpace: sampleSpace = OpenMaya.MSpace.kWorld else: sampleSpace = OpenMaya.MSpace.kObject # Write mesh cache for f in range(startFrame,endFrame+1): # Update frame mc.currentTime(f) mc.dgdirty(a=True) # Check mesh visibility meshList = [mesh for mesh in fullMeshList if mc.getAttr(mesh+'.v')] if not meshList: continue # ------------------------- # - Open file for writing - # ------------------------- fPad = glTools.utils.stringUtils.stringIndex(f,pad) if gz: filename = path+'/'+name+'.'+fPad+'.obj.gz' print 'Writing '+filename FILE = gzip.open(filename,"wb") else: filename = path+'/'+name+'.'+fPad+'.obj' print 'Writing '+filename FILE = open(filename,"w") # Write cache file header FILE.write('g\n') # --------------------- # - Write Vertex Data - # --------------------- # Write raw point data for m in range(len(meshList)): meshFn = glTools.utils.mesh.getMeshFn(meshList[m]) # Vertex Positions vtxArray = OpenMaya.MPointArray() meshFn.getPoints(vtxArray,sampleSpace) for i in range(vtxArray.length()): FILE.write('v '+str(vtxArray[i].x)+' '+str(vtxArray[i].y)+' '+str(vtxArray[i].z)+'\n') # Vertex UVs if uvSet: uvSetName = uvSet else: uvSetName = str(mc.polyUVSet(meshList[m],q=True,cuv=True)[0]) uArray = OpenMaya.MFloatArray() vArray = OpenMaya.MFloatArray() meshFn.getUVs(uArray,vArray,uvSetName) for i in range(uArray.length()): FILE.write('vt '+str(uArray[i])+' '+str(vArray[i])+'\n') # Vertex Normals normArray = OpenMaya.MFloatVectorArray() meshFn.getVertexNormals(False,normArray,sampleSpace) for i in range(vtxArray.length()): FILE.write('vn '+str(vtxArray[i].x)+' '+str(vtxArray[i].y)+' '+str(vtxArray[i].z)+'\n') # ------------------- # - Write Face Data - # ------------------- # Track per mesh vertex id offsets vertexOffset = 0 uvOffset = 0 # Initialize face vertex array faceVtxArray = OpenMaya.MIntArray() # Build UV Id pointer object uvIdUtil = OpenMaya.MScriptUtil() uvIdUtil.createFromInt(0) uvIdPtr = uvIdUtil.asIntPtr() # Iterate over meshes for m in range(len(meshList)): # Write cache file header grp = meshList[m].replace(':','_').lower() FILE.write('g '+grp+'\n') # Get mesh face iterator faceIter = glTools.utils.mesh.getMeshFaceIter(meshList[m]) # Iterate over mesh faces faceIter.reset() while not faceIter.isDone(): # Get face vertices faceIter.getVertices(faceVtxArray) vtxArray = list(faceVtxArray) vtxCount = len(vtxArray) # Build face data string faceData = 'f ' for i in range(vtxCount): # Vertex Id faceData += str(vtxArray[i]+1+vertexOffset) faceData += '/' # UV Id try: faceIter.getUVIndex(i,uvIdPtr) except: pass else: faceData += str(OpenMaya.MScriptUtil(uvIdPtr).asInt()+1+uvOffset) faceData += '/' # Vertex Normal Id faceData += str(vtxArray[i]+1+vertexOffset) faceData += ' ' faceData += '\n' # Write face data FILE.write(faceData) # Iterate to next face faceIter.next() # Update vertex offset vertexOffset += mc.polyEvaluate(meshList[m],v=True) uvOffset += mc.polyEvaluate(meshList[m],uv=True,uvs=uvSetName) # ----------------------- # - Finalize cache file - # ----------------------- # Close File FILE.close() # Print result print 'Write OBJ cache completed!'
def bake_poses_to_timeline(self, start_frame=0, suppress=False, anim_layer=None): """ Bakes the poses to the timeline and sets the time range to the given animation. :param start_frame: start frame of he baked animation :param suppress: A bool to suppress the warning dialogue. Meant to be used outside of the UI :anim_layer: if given the animations will be baked on that layer.If the layer doesnt exist we will create one. """ bake_bool = True pose_list = [] if not anim_layer: anim_layer = "BaseAnimation" elif not cmds.animLayer(anim_layer, exists=True): cmds.animLayer(anim_layer) try: cmds.autoKeyframe(e=1, st=0) if not suppress: ret = QtWidgets.QMessageBox.warning(None, "WARNING: DESTRUCTIVE FUNCTION", "This will bake the poses to the timeline, change your time range, and delete inputs on driving and driven transforms.\n" + \ "Do you want this to happen?", QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel, QtWidgets.QMessageBox.Cancel) if ret == QtWidgets.QMessageBox.StandardButton.Ok: bake_bool = True cmds.undoInfo(openChunk=True, undoName='Bake poses to timeline') else: bake_bool = False if bake_bool: # begin printing UE4 pose list # print('<- UE4 Pose List ---------------------->') i = start_frame for p in self.pose_dict: driven_xforms = [] for mx_node in self.pose_dict[p]: driven_xforms.extend( cmds.listConnections(mx_node + '.driven_transform')) # let's key it on the previous and next frames before we pose it cmds.select(driven_xforms) cmds.animLayer(anim_layer, addSelectedObjects=True, e=True) cmds.setKeyframe(driven_xforms, t=[(i - 1), (i + 1)], animLayer=anim_layer) # assume the pose self.assume_pose(p) cmds.setKeyframe(driven_xforms, t=[i], animLayer=anim_layer) # print out to UE4 pose list print(p) pose_list.append(p) # increment to next keyframe i += 1 # print('<- UE4 Pose List ---------------------->') # set the range to the number of keyframes cmds.playbackOptions(minTime=0, maxTime=i, animationStartTime=0, animationEndTime=i - 1) cmds.dgdirty(a=1) return pose_list cmds.dgdirty(a=1) except Exception as e: print(traceback.format_exc()) finally: cmds.undoInfo(closeChunk=True)
def setActiveKeys(node, delete=False) : print "Setting active on : " + str(node) + " delete is: " + str(delete) ''' sets the value of .actve attribute on a peel marker to being 1 or 0 if data exists one the translate.x channel. This is used to change the display of the marker from a square to a cross in the display. ''' try : node = fixName(node) except RuntimeError as e : m.warning( str(e) ) return if type(node) not in [ str, unicode ] : raise ValueError("Invalid type for setActiveKeys: " + str(type(node))) interval = datarate.get(node) if interval is None : m.warning("No interval for node while setting active keys: " + str(node) ) return if m.nodeType(node) != "transform" : m.warning("Not a transform while setting active: " + str(node) + ' ' + str( m.nodeType(node) )) return if not m.objExists(node) : m.warning("Object does not exist while setting active: " + str(node) ) return if not m.objExists(node + ".active") : m.warning("Object does not have active channel while setting active keys: " + str(node) ) return # check the tx time values times = m.keyframe(node + ".tx", q=True, timeChange=True) if times is None : print "No keys on: " + str(node) conn = m.listConnections( node, d=True, s=False,type='PeelLine', p=True) if delete and ( conn is None or len(conn) == 0 ) : m.delete( node) else : m.cutKey( node + '.active' ) m.setAttr( node + '.active', 0 ) return times = sorted( times ) if len(times) == 0 : return cdata = curve.fcurve(node, "atv") # iterate over each frame and set the active channel when the state changes (stepped) lastFrame = None for frame in times : if lastFrame is None : # first frame cdata.data[frame - interval] = 0.0 cdata.data[frame] = 1.0 else : gapsize = frame-lastFrame if abs(gapsize - interval) > 0.1 : #print str( gapsize ) + ' ' + str(interval) + ' ' + str( abs(gapsize - interval) ) + ' ' + str(frame) cdata.data[lastFrame + interval ] = 0.0 cdata.data[frame] = 1.0 lastFrame = frame cdata.data[times[-1]+interval] = 0 cdata.apply(stepped=True) m.dgdirty( node )
def force_eval(mtime, _): # Without dgdirty some animation were not updated in mayapy mc.dgdirty(allPlugs=True)
def createRig(self): #________________________________________TO MODIF <------------------------ START buildRigClass.buildRig.createRig(self) ''' build the rig a partir des subRig deja cree you have: self.mainGrp self.manipGrp self.rigGrp self.subRigObjs -------> the obj of all subRig self.buildTrs -------> world trsValue of selection self.alls = [] # a remplir avec chaque element cree dans createRig!!!!! ''' self.alls = [] #<------ a remplir trsObj = trsClass.trsClass() chainDynObjs = self.subRigObjs # BASE HIERARCHY hierarchyNames = [self.mainGrp, self.manipGrp, self.rigGrp] hierarchyTypes = ['transform', 'transform', 'transform'] hierarchyFathers = ['', self.mainGrp, self.mainGrp] utilsMaya.createDagNodes(hierarchyTypes, hierarchyNames, hierarchyFathers) self.alls += hierarchyNames # PARENT SUBRIG for i in range(0, len(chainDynObjs)): mc.parent(chainDynObjs[i].mainGrp, self.manipGrp) # SLAVE LOC mc.spaceLocator(n=self.outLoc) mc.parent(self.outLoc, self.rigGrp) mc.setAttr(self.outLoc + '.visibility', 0) self.alls += [self.outLoc] # COLLISION PLANE mc.nurbsPlane(n=self.collisionPlane, p=[0, 0, 0], ax=[1, 0, 0], w=1, lr=1, d=1, u=1, v=1, ch=1) trsObj.toObj(self.collisionPlane, inTrsValue=self.trsCollisionPlane) mc.parent(self.collisionPlane, self.rigGrp) utilsMaya.buildConstraint([ self.collisionPlane, chainDynObjs[0].collisionPlane, chainDynObjs[1].collisionPlane, chainDynObjs[2].collisionPlane, chainDynObjs[3].collisionPlane, chainDynObjs[4].collisionPlane ], ['parent'], 'oneMaster', 0) self.alls += [self.collisionPlane] # NODE CONNECTION mc.createNode(self.nodeType, n=self.nodeName) mc.connectAttr(self.nodeName + '.outTranslate', self.outLoc + '.translate') mc.connectAttr(self.nodeName + '.outRotate', self.outLoc + '.rotate') mc.connectAttr(chainDynObjs[0].outs[0] + '.worldMatrix[0]', self.nodeName + '.worldMatrixA') mc.connectAttr(chainDynObjs[1].outs[0] + '.worldMatrix[0]', self.nodeName + '.worldMatrixB') mc.connectAttr(chainDynObjs[2].outs[0] + '.worldMatrix[0]', self.nodeName + '.worldMatrixC') mc.connectAttr(chainDynObjs[3].outs[0] + '.worldMatrix[0]', self.nodeName + '.worldMatrixD') self.alls += [self.nodeName] # OTHER mc.refresh() mc.dgdirty(self.nodeName) utilsMaya.buildConstraint([self.outLoc, chainDynObjs[4].ins[0]], ['parent'], 'oneMaster', 1) #____WRITE BUILD INFO buildTrs = self.buildTrs ins = [ chainDynObjs[0].ins[0], chainDynObjs[1].ins[0], chainDynObjs[2].ins[0], chainDynObjs[3].ins[0] ] ctrls = [obj.ctrls[0] for obj in chainDynObjs] outs = [chainDynObjs[4].outs[0]] subMainGrps = [rigObj.mainGrp for rigObj in self.subRigObjs] beacons = subMainGrps self.saveWriteMainGrpAttr(self.mainGrp, self.rigType, buildTrs, ins, ctrls, outs, beacons, self.alls, subMainGrps) self.writeBeaconsAttr()