def saveAnim(path, objects=None, time=None, sampleBy=1, metadata=None, bakeConnected=False): """ Save the anim data for the given objects. Example: anim = "C:/example.anim" anim = saveAnim(path, metadata={'description': 'Example anim'}) print anim.metadata() # {'description': 'test', 'user': '******', 'mayaVersion': u'2016'} :type path: str :type objects: None or list[str] :type time: None or int :type sampleBy: int :type metadata: dict or None :type bakeConnected: bool :rtype: mutils.Animation """ step = 1 objects = objects or maya.cmds.ls(selection=True) or [] if not objects: raise Exception( "No objects selected. Please select at least one object.") if not time: time = mutils.selectedObjectsFrameRange(objects) start, end = time if start >= end: msg = "The start frame cannot be greater than or equal to the end frame!" raise AnimationTransferError(msg) iconPath = path + "/thumbnail.jpg" sequencePath = path + "/sequence/thumbnail.jpg" sequencePath = mutils.createSnapshot( path=sequencePath, start=start, end=end, step=step, ) if iconPath: shutil.copyfile(sequencePath, iconPath) anim = mutils.Animation.fromObjects(objects) if metadata: anim.updateMetadata(metadata) anim.save(path, time=time, bakeConnected=bakeConnected, sampleBy=sampleBy) return anim
def __init__(self, parent=None): super(FrameRangeMenu, self).__init__(parent) action = FrameRangeAction("From Timeline", self) action.setFrameRange(mutils.playbackFrameRange()) self.addAction(action) action = FrameRangeAction("From Selected Timeline", self) action.setFrameRange(mutils.selectedFrameRange()) self.addAction(action) action = FrameRangeAction("From Selected Objects", self) action.setFrameRange(mutils.selectedObjectsFrameRange()) self.addAction(action)
def save(self, path, time=None, sampleBy=1, fileType="", bakeConnected=True): """ Save all animation data from the objects set on the Anim object. :type path: str :type time: (int, int) or None :type sampleBy: int :type fileType: str :type bakeConnected: bool :rtype: None """ objects = self.objects().keys() fileType = fileType or DEFAULT_FILE_TYPE if not time: time = mutils.selectedObjectsFrameRange(objects) start, end = time # Check selected animation layers gSelectedAnimLayers = maya.mel.eval( '$gSelectedAnimLayers=$gSelectedAnimLayers') if len(gSelectedAnimLayers) > 1: msg = "More than one animation layer is selected! Please select only one animation layer for export!" raise AnimationTransferError(msg) # Check frame range if start is None or end is None: msg = "Please specify a start and end frame!" raise AnimationTransferError(msg) if start >= end: msg = "The start frame cannot be greater than or equal to the end frame!" raise AnimationTransferError(msg) # Check if animation exists if mutils.getDurationFromNodes(nodes=objects or []) <= 0: msg = "No animation was found on the specified object/s! Please create a pose instead!" raise AnimationTransferError(msg) self.setMetadata("endFrame", end) self.setMetadata("startFrame", start) end += 1 dstCurves = [] validAnimCurves = [] msg = "Animation.save(path={0}, time={1}, bakeConnections={2}, sampleBy={3})" msg = msg.format(path, str(time), str(bakeConnected), str(sampleBy)) logger.debug(msg) try: if bakeConnected: maya.cmds.undoInfo(openChunk=True) mutils.bakeConnected(objects, time=(start, end), sampleBy=sampleBy) for name in objects: if maya.cmds.copyKey(name, time=(start, end), includeUpperBound=False, option="keys"): # Might return more than one object when duplicating shapes or blendshapes transform, = maya.cmds.duplicate(name, name="CURVE", parentOnly=True) dstCurves.append(transform) mutils.disconnectAll(transform) maya.cmds.pasteKey(transform) attrs = maya.cmds.listAttr( transform, unlocked=True, keyable=True) or [] attrs = list( set(attrs) - set(['translate', 'rotate', 'scale'])) for attr in attrs: fullname = ("%s.%s" % (transform, attr)) dstCurve, = maya.cmds.listConnections( fullname, destination=False) or [None] if dstCurve: # Filter to only animCurves since you can have proxy attributes if not maya.cmds.nodeType(dstCurve).startswith( "animCurve"): continue dstCurve = maya.cmds.rename(dstCurve, "CURVE") srcCurve = mutils.animCurve("%s.%s" % (name, attr)) if srcCurve and "animCurve" in maya.cmds.nodeType( srcCurve): preInfinity = maya.cmds.getAttr(srcCurve + ".preInfinity") postInfinity = maya.cmds.getAttr( srcCurve + ".postInfinity") curveColor = maya.cmds.getAttr(srcCurve + ".curveColor") useCurveColor = maya.cmds.getAttr( srcCurve + ".useCurveColor") maya.cmds.setAttr(dstCurve + ".preInfinity", preInfinity) maya.cmds.setAttr(dstCurve + ".postInfinity", postInfinity) maya.cmds.setAttr(dstCurve + ".curveColor", *curveColor[0]) maya.cmds.setAttr(dstCurve + ".useCurveColor", useCurveColor) dstCurves.append(dstCurve) if maya.cmds.keyframe(dstCurve, query=True, time=(start, end), keyframeCount=True): self.setAnimCurve(name, attr, dstCurve) maya.cmds.cutKey(dstCurve, time=(MIN_TIME_LIMIT, start - 1)) maya.cmds.cutKey(dstCurve, time=(end + 1, MAX_TIME_LIMIT)) validAnimCurves.append(dstCurve) fileName = "animation.ma" if fileType == "mayaBinary": fileName = "animation.mb" mayaPath = os.path.join(path, fileName) posePath = os.path.join(path, "pose.json") mutils.Pose.save(self, posePath) if validAnimCurves: maya.cmds.select(validAnimCurves) logger.info("Saving animation: %s" % mayaPath) maya.cmds.file(mayaPath, force=True, options='v=0', type=fileType, uiConfiguration=False, exportSelected=True) self.cleanMayaFile(mayaPath) finally: if bakeConnected: # HACK! Undo all baked connections. :) maya.cmds.undoInfo(closeChunk=True) maya.cmds.undo() elif dstCurves: maya.cmds.delete(dstCurves) self.setPath(path)
def save( self, path, time=None, sampleBy=1, fileType="", bakeConnected=True ): """ Save all animation data from the objects set on the Anim object. :type path: str :type time: (int, int) or None :type sampleBy: int :type fileType: str :type bakeConnected: bool :rtype: None """ objects = self.objects().keys() logger.debug(("objects = {0}").format(objects)) fileType = fileType or DEFAULT_FILE_TYPE if not time: time = mutils.selectedObjectsFrameRange(objects) start, end = time # Check selected animation layers validateAnimLayers() # Check frame range if start is None or end is None: msg = "Please specify a start and end frame!" raise AnimationTransferError(msg) if start >= end: msg = "The start frame cannot be greater than or equal to the end frame!" raise AnimationTransferError(msg) # Check if animation exists if mutils.getDurationFromNodes(objects or []) <= 0: msg = "No animation was found on the specified object/s! " \ "Please create a pose instead!" raise AnimationTransferError(msg) self.setMetadata("endFrame", end) self.setMetadata("startFrame", start) end += 1 validCurves = [] deleteObjects = [] msg = u"Animation.save(path={0}, time={1}, bakeConnections={2}, sampleBy={3})" msg = msg.format(path, str(time), str(bakeConnected), str(sampleBy)) logger.debug(msg) try: if bakeConnected: maya.cmds.undoInfo(openChunk=True) mutils.bakeConnected(objects, time=(start, end), sampleBy=sampleBy) for name in objects: if maya.cmds.copyKey(name, time=(start, end), includeUpperBound=False, option="keys"): logger.debug(name) # Might return more than one object when duplicating shapes or blendshapes # transform = maya.cmds.duplicate(name, name="CURVE", parentOnly=True) # if not FIX_SAVE_ANIM_REFERENCE_LOCKED_ERROR: # mutils.disconnectAll(transform[0]) # deleteObjects.append(transform[0]) # maya.cmds.pasteKey(transform[0]) attrs = [] name_type_list = maya.cmds.ls(name, showType = True) if name_type_list[1] == BLEND_SHAPE_TYPE: attrs = self.getBlendshapeParamList(name) else: attrs = maya.cmds.listAttr(name, unlocked=True, keyable=True) or [] attrs = list(set(attrs) - set(['translate', 'rotate', 'scale'])) logger.debug(("attrs = {0}").format(attrs)) for attr in attrs: logger.debug(("transform name = {0}, attr name = {1}").format(name, attr)) dstAttr = mutils.Attribute(name, attr) dstCurve = dstAttr.animCurve() if dstCurve: # dstCurve = maya.cmds.rename(dstCurve, "CURVE") # deleteObjects.append(dstCurve) # srcAttr = mutils.Attribute(name, attr) # srcCurve = srcAttr.animCurve() # if srcCurve: # preInfinity = maya.cmds.getAttr(srcCurve + ".preInfinity") # postInfinity = maya.cmds.getAttr(srcCurve + ".postInfinity") # curveColor = maya.cmds.getAttr(srcCurve + ".curveColor") # useCurveColor = maya.cmds.getAttr(srcCurve + ".useCurveColor") # maya.cmds.setAttr(dstCurve + ".preInfinity", preInfinity) # maya.cmds.setAttr(dstCurve + ".postInfinity", postInfinity) # maya.cmds.setAttr(dstCurve + ".curveColor", *curveColor[0]) # maya.cmds.setAttr(dstCurve + ".useCurveColor", useCurveColor) if maya.cmds.keyframe(dstCurve, query=True, time=(start, end), keyframeCount=True): self.setAnimCurve(name, attr, dstCurve) # maya.cmds.cutKey(dstCurve, time=(MIN_TIME_LIMIT, start - 1)) # maya.cmds.cutKey(dstCurve, time=(end + 1, MAX_TIME_LIMIT)) validCurves.append(dstCurve) fileName = "animation.ma" if fileType == "mayaBinary": fileName = "animation.mb" mayaPath = os.path.join(path, fileName) posePath = os.path.join(path, "pose.json") mutils.Pose.save(self, posePath) if validCurves: maya.cmds.select(validCurves) logger.info("Saving animation: %s" % mayaPath) maya.cmds.file(mayaPath, force=True, options='v=0', type=fileType, uiConfiguration=False, exportSelected=True) self.cleanMayaFile(mayaPath) finally: if bakeConnected: # HACK! Undo all baked connections. :) maya.cmds.undoInfo(closeChunk=True) maya.cmds.undo() elif deleteObjects: maya.cmds.delete(deleteObjects) self.setPath(path)
def saveAnim( path, objects=None, time=None, sampleBy=1, metadata=None, bakeConnected=False ): """ Save the anim data for the given objects. Example: import mutils mutils.saveAnim( path="c:/example.anim", time=(1, 20), metadata={'description': 'Example anim'} ) :type path: str :type objects: None or list[str] :type time: None or int :type sampleBy: int :type metadata: dict or None :type bakeConnected: bool :rtype: mutils.Animation """ step = 1 objects = objects or maya.cmds.ls(selection=True) or [] if os.path.exists(path): raise Exception("Cannot override an existing path. " + path) if not objects: raise Exception( "No objects selected. Please select at least one object." ) if not time: time = mutils.selectedObjectsFrameRange(objects) start, end = time if start >= end: msg = "The start frame cannot be greater than or equal to the end frame!" raise AnimationTransferError(msg) tmpPath = mutils.TempDir("anim", clean=True).path() os.makedirs(tmpPath + '/sequence') iconPath = tmpPath + "/thumbnail.jpg" sequencePath = tmpPath + "/sequence/thumbnail.jpg" window = mutils.gui.thumbnailCapture( path=sequencePath, startFrame=start, endFrame=end, step=step, modifier=False, ) if iconPath: shutil.copyfile(window.capturedPath(), iconPath) anim = mutils.Animation.fromObjects(objects) if metadata: anim.updateMetadata(metadata) anim.save(tmpPath, time=time, bakeConnected=bakeConnected, sampleBy=sampleBy) shutil.copytree(tmpPath, path) return mutils.Animation.fromPath(path)
def save( self, path, time=None, sampleBy=1, fileType="", bakeConnected=True ): """ Save all animation data from the objects set on the Anim object. :type path: str :type time: (int, int) or None :type sampleBy: int :type fileType: str :type bakeConnected: bool :rtype: None """ objects = self.objects().keys() fileType = fileType or DEFAULT_FILE_TYPE if not time: time = mutils.selectedObjectsFrameRange(objects) start, end = time # Check selected animation layers validateAnimLayers() # Check frame range if start is None or end is None: msg = "Please specify a start and end frame!" raise AnimationTransferError(msg) if start >= end: msg = "The start frame cannot be greater than or equal to the end frame!" raise AnimationTransferError(msg) # Check if animation exists if mutils.getDurationFromNodes(objects or []) <= 0: msg = "No animation was found on the specified object/s! " \ "Please create a pose instead!" raise AnimationTransferError(msg) self.setMetadata("endFrame", end) self.setMetadata("startFrame", start) end += 1 validCurves = [] deleteObjects = [] msg = "Animation.save(path={0}, time={1}, bakeConnections={2}, sampleBy={3})" msg = msg.format(path, str(time), str(bakeConnected), str(sampleBy)) logger.debug(msg) try: if bakeConnected: maya.cmds.undoInfo(openChunk=True) mutils.bakeConnected(objects, time=(start, end), sampleBy=sampleBy) for name in objects: if maya.cmds.copyKey(name, time=(start, end), includeUpperBound=False, option="keys"): # Might return more than one object when duplicating shapes or blendshapes transform, = maya.cmds.duplicate(name, name="CURVE", parentOnly=True) if not FIX_SAVE_ANIM_REFERENCE_LOCKED_ERROR: mutils.disconnectAll(transform) deleteObjects.append(transform) maya.cmds.pasteKey(transform) attrs = maya.cmds.listAttr(transform, unlocked=True, keyable=True) or [] attrs = list(set(attrs) - set(['translate', 'rotate', 'scale'])) for attr in attrs: dstAttr = mutils.Attribute(transform, attr) dstCurve = dstAttr.animCurve() if dstCurve: dstCurve = maya.cmds.rename(dstCurve, "CURVE") deleteObjects.append(dstCurve) srcAttr = mutils.Attribute(name, attr) srcCurve = srcAttr.animCurve() if srcCurve: preInfinity = maya.cmds.getAttr(srcCurve + ".preInfinity") postInfinity = maya.cmds.getAttr(srcCurve + ".postInfinity") curveColor = maya.cmds.getAttr(srcCurve + ".curveColor") useCurveColor = maya.cmds.getAttr(srcCurve + ".useCurveColor") maya.cmds.setAttr(dstCurve + ".preInfinity", preInfinity) maya.cmds.setAttr(dstCurve + ".postInfinity", postInfinity) maya.cmds.setAttr(dstCurve + ".curveColor", *curveColor[0]) maya.cmds.setAttr(dstCurve + ".useCurveColor", useCurveColor) if maya.cmds.keyframe(dstCurve, query=True, time=(start, end), keyframeCount=True): self.setAnimCurve(name, attr, dstCurve) maya.cmds.cutKey(dstCurve, time=(MIN_TIME_LIMIT, start - 1)) maya.cmds.cutKey(dstCurve, time=(end + 1, MAX_TIME_LIMIT)) validCurves.append(dstCurve) fileName = "animation.ma" if fileType == "mayaBinary": fileName = "animation.mb" mayaPath = os.path.join(path, fileName) posePath = os.path.join(path, "pose.json") mutils.Pose.save(self, posePath) if validCurves: maya.cmds.select(validCurves) logger.info("Saving animation: %s" % mayaPath) maya.cmds.file(mayaPath, force=True, options='v=0', type=fileType, uiConfiguration=False, exportSelected=True) self.cleanMayaFile(mayaPath) finally: if bakeConnected: # HACK! Undo all baked connections. :) maya.cmds.undoInfo(closeChunk=True) maya.cmds.undo() elif deleteObjects: maya.cmds.delete(deleteObjects) self.setPath(path)
def save(self, path, time=None, sampleBy=1, fileType="", bakeConnected=True): """ Save all animation data from the objects set on the Anim object. :type path: str :type time: (int, int) or None :type sampleBy: int :type fileType: str :type bakeConnected: bool :rtype: None """ objects = self.objects().keys() logger.debug(("objects = {0}").format(objects)) fileType = fileType or DEFAULT_FILE_TYPE if not time: time = mutils.selectedObjectsFrameRange(objects) start, end = time # Check selected animation layers validateAnimLayers() # Check frame range if start is None or end is None: msg = "Please specify a start and end frame!" raise AnimationTransferError(msg) if start >= end: msg = "The start frame cannot be greater than or equal to the end frame!" raise AnimationTransferError(msg) # Check if animation exists if mutils.getDurationFromNodes(objects or []) <= 0: msg = "No animation was found on the specified object/s! " \ "Please create a pose instead!" raise AnimationTransferError(msg) self.setMetadata("endFrame", end) self.setMetadata("startFrame", start) end += 1 validCurves = [] # deleteObjects = [] # msg = u"Animation.save(path={0}, time={1}, bakeConnections={2}, sampleBy={3})" # msg = msg.format(path, str(time), str(bakeConnected), str(sampleBy)) # logger.debug(msg) try: if bakeConnected: maya.cmds.undoInfo(openChunk=True) mutils.bakeConnected(objects, time=(start, end), sampleBy=sampleBy) for name in objects: if maya.cmds.copyKey(name, time=(start, end), includeUpperBound=False, option="keys"): attrs = maya.cmds.listAttr( name, unlocked=True, keyable=True) or [] attrs = list( set(attrs) - set(['translate', 'rotate', 'scale'])) self.listAttachedAnimCurves(name) for attr in attrs: dstAttr = mutils.Attribute(name, attr) dstCurve = dstAttr.animCurve() logger.debug(("dstCurve = {0}").format(dstCurve)) if dstCurve: srcAttr = mutils.Attribute(name, attr) srcCurve = srcAttr.animCurve() if maya.cmds.keyframe(dstCurve, query=True, time=(start, end), keyframeCount=True): self.setAnimCurve(name, attr, dstCurve) validCurves.append(dstCurve) fileName = "animation.ma" if fileType == "mayaBinary": fileName = "animation.mb" mayaPath = os.path.join(path, fileName) posePath = os.path.join(path, "pose.json") mutils.Pose.save(self, posePath) if validCurves: maya.cmds.select(validCurves) logger.info("Saving animation: %s" % mayaPath) maya.cmds.file(mayaPath, force=True, options='v=0', type=fileType, uiConfiguration=False, exportSelected=True) self.cleanMayaFile(mayaPath) finally: if bakeConnected: # HACK! Undo all baked connections. :) maya.cmds.undoInfo(closeChunk=True) maya.cmds.undo() self.setPath(path)