def flipAnimation(self): """ 選択したオブジェクトのアニメーションを反転します チェックボックスを入れたアトリビュートのアニメーションカーブ-1をかける """ nodes = cmds.ls(sl=True) node = nodes[0] if not nodes: return attribute = [] if self.flipTranslateXcheck.checkState(): attribute.append("translateX") if self.flipTranslateYcheck.checkState(): attribute.append("translateY") if self.flipTranslateZcheck.checkState(): attribute.append("translateZ") if self.flipRotateXcheck.checkState(): attribute.append("rotateX") if self.flipRotateYcheck.checkState(): attribute.append("rotateY") if self.flipRotateZcheck.checkState(): attribute.append("rotateZ") # アトリビュートが選択されてなかったら終了 if not attribute: return cmds.scaleKey(node,at=attribute,valueScale = -1)
def scale_face_joint_anim(namespace='Tier1_Male_01', scale=1.0): """Scale animation on face joints. Args: namespace (str): namespace of skeleton to read joints from scale (float): anim scale (1.0 has no effect) """ # Get curves to scale _to_scale = [] for _jnt in sorted(SCALE_ANIM_JNTS): for _attr in ['tx', 'ty', 'tz', 'rx', 'ry', 'rz']: _plug = '{}:{}.{}'.format(namespace, _jnt, _attr) _key = '{}.{}'.format(_jnt, _attr) _rest_val = _REST_POSES.get(_key, 0) _crvs = cmds.listConnections(_plug, destination=False, type='animCurve') if not _crvs: continue _crv = _crvs[0] _to_scale.append((_crv, _rest_val)) print 'FOUND {:d} CURVES TO SCALE'.format(len(_to_scale)) # Apply scaling for _crv, _rest_val in _to_scale: cmds.scaleKey(_crv, valueScale=scale, valuePivot=_rest_val) print 'SCALED {:d} CURVES - scale={:.03f}'.format(len(_to_scale), scale)
def applyCallback(*pArgs): # print "-------------applyCallback----------------" # print "first mode= %s" %_mode # print "first key= %s" %_key # print "attri key= %s" %_attri # call function to chect array after press "apply" checkList() global index index=0 nowJ=cmds.ls(orderedSelection=True) nowTime=mc.currentTime(q=1) for i in nowJ: # print "now i= %s" %i index += 1 if index >= 2: targetJ=nowJ[index-1] # print "target obj is = %s" %(targetJ) if _key == 2: #all key cmds.copyKey(nowJ,at=_attri) cmds.pasteKey(targetJ,at=_attri,option="replace") if _mode == 2: cmds.scaleKey(targetJ,at=_attri,valueScale=-1) else: # single key cmds.copyKey(nowJ,at=_attri,time=(nowTime,nowTime)) cmds.pasteKey(targetJ) if _mode == 2: cmds.scaleKey(targetJ,at=_attri,valueScale=-1,time=(nowTime,nowTime))
def converge_buffer(option): keyCount = cmds.keyframe(q=True, kc=True, sl=True) if keyCount == 0: return cmds.undoInfo(openChunk=True, chunkName="converge_buffer") if option == "toward": scaleValue = 0.9 elif option == "away": scaleValue = 1 / 0.9 else: cmds.undoInfo(closeChunk=True, chunkName="converge_buffer") return selectedCurves = cmds.keyframe(q=True, n=True, sl=True) for crv in selectedCurves: timeArray = cmds.keyframe(crv, q=True, tc=True, sl=True) cmds.bufferCurve(swap=True) burrferValues = [] for t in timeArray: burrferValues.append( cmds.keyframe(crv, time=(t, t), q=True, eval=True)[0]) cmds.bufferCurve(swap=True) selectedValues = cmds.keyframe(crv, q=True, iv=True, sl=True) for i, slv in enumerate(selectedValues): cmds.scaleKey(crv, index=(slv, slv), vp=burrferValues[i], vs=scaleValue) cmds.undoInfo(closeChunk=True, chunkName="converge_buffer")
def animScale(v): try: v = float(v) # scale_pivot = cmds.playbackOptions(q=True, min=True) scale_pivot = cmds.currentTime(q=True) cmds.scaleKey(ts=v, tp=scale_pivot) except: message('didnt work') return None
def bakeSequenceScale(s): print "baking shot camera: ", s #create shot render cam renderCam = mc.shot(s, cc=True, q=True) copiedRenderCam = mc.duplicate(renderCam, name=renderCam + "_baked_" + s, un=True)[0] print "copied render cam for ", s, " : ", copiedRenderCam #shot sequence vars seq_startTime = mc.shot(s, sst=True, q=True) seq_endTime = mc.shot(s, set=True, q=True) seq_duration = mc.shot(s, sequenceDuration=True, q=True) #get shot info #this assumes start time is never subframe startTime = mc.shot(s, st=True, q=True) #get actual end time, api endtime doesnt return subframe. mc.sequenceManager(currentTime=seq_endTime) endTime = mc.currentTime(q=True) print renderCam, ":" print "camera time:", startTime, "=>", endTime #set current time to start time mc.setKeyframe(copiedRenderCam, hi="both", t=startTime) print "Created initial keys" mc.setKeyframe(copiedRenderCam, hi="both", t=endTime) print "Created ending keys" #remove any keyframes that's not in this frame range print "cleanup keyframes." mc.cutKey(copiedRenderCam, clear=True, time=(":" + str(startTime - 0.01), ), option="keys") mc.cutKey(copiedRenderCam, clear=True, time=(str(endTime + 0.01) + ":", ), option="keys") #set end time to scale scaleEndTime = startTime + seq_duration - 1 print "scaling to: ", startTime, " => ", scaleEndTime mc.scaleKey(copiedRenderCam, time=(startTime, endTime), newStartTime=startTime, newEndTime=scaleEndTime, timePivot=0) return copiedRenderCam
def swapAnimation(fromNode, toNode): if not mc.keyframe(fromNode, query=True, name=True): mc.cutKey(toNode, clear=True) return attrs = mc.listAttr(fromNode, keyable=True) if not attrs: return for attr in attrs: if not mc.attributeQuery(attr, node=toNode, exists=True): mc.cutKey(fromNode, attribute=attr, clear=True) continue fromPlug = '{}.{}'.format(fromNode, attr) toPlug = '{}.{}'.format(toNode, attr) srcCurve = mc.listConnections(fromPlug, source=True, destination=False, type='animCurve') dstCurve = mc.listConnections(toPlug, source=True, destination=False, type='animCurve') copySrc = None copyDst = None if srcCurve: copySrc = mc.duplicate(srcCurve[0])[0] if dstCurve: copyDst = mc.duplicate(dstCurve[0])[0] if copySrc: try: mc.cutKey(copySrc) mc.pasteKey(toNode, attribute=attr, option='replaceCompletely') except: pass if copyDst: try: mc.cutKey(copyDst) mc.pasteKey(fromNode, attribute=attr, option='replaceCompletely') except: pass for axis in getMirrorAxis(toNode): mc.scaleKey(toNode, attribute=axis, valueScale=-1) mc.scaleKey(fromNode, attribute=axis, valueScale=-1)
def favorPrevious(): curves = mc.keyframe(q=1, name=1) if len( mc.ls(sl=1) ): for curve in curves: targetIndex = mc.keyframe(curve, q=1 ,sl=1, iv=1) targetIndex[0] = targetIndex[0] - 1 pivotIndex = tuple(targetIndex) targetIndex[0] = targetIndex[0] + 1 targetIndex = tuple(targetIndex) pivotValue = mc.keyframe(curve, index=pivotIndex, q=1, vc=1)[0] mc.scaleKey(curve, vs=0.95, vp=pivotValue, index=targetIndex)
def retime(animation_curves, start_frame, end_frame, new_start_frame, new_end_frame, offset_contiguous_animation=True, snap_keys=True): """Scale time range but also offset what's contiguous to keep continuity""" # Define offsets happening before and after: end_offset = new_end_frame - end_frame start_offset = new_start_frame - start_frame # Define offset functions: keys = mc.keyframe(animation_curves, query=True) max_keyframe = max(keys) + start_offset + end_offset offset_after_function = partial(mc.keyframe, animation_curves, edit=True, t=(end_frame + 1, max_keyframe), relative=True, timeChange=end_offset, option='over') min_keyframe = min(keys) - end_offset - start_offset offset_before_function = partial(mc.keyframe, animation_curves, edit=True, t=(min_keyframe, start_frame - 1), relative=True, timeChange=start_offset, option='over') # Offsets in case of expansion: if offset_contiguous_animation and end_offset > 0: offset_after_function() if offset_contiguous_animation and start_offset < 0: offset_before_function() # Retime/scale animation: mc.scaleKey(animation_curves, time=(start_frame, end_frame), newStartTime=new_start_frame, newEndTime=new_end_frame) if snap_keys: mc.snapKey(animation_curves, t=(new_start_frame, new_end_frame)) # Offsets in case of shrinking: if offset_contiguous_animation and end_offset < 0: offset_after_function() if offset_contiguous_animation and start_offset > 0: offset_before_function()
def mirror_y(dragControl, x, y, modifiers): if modifiers == 0: try: mel.eval('doBuffer snapshot') mel.eval('doBuffer swap') cmds.scaleKey(scaleSpecifiedKeys=True, timeScale=1, timePivot=0, floatScale=1, floatPivot=0, valueScale=-1, valuePivot=0) except: print 'Animation Key is Not Selected'
def reverse_keys_horizontal(): if cmds.scaleKey(attribute=True): # Is a key/curve selected? keys = cmds.keyframe(query=True, selected=True, timeChange=True) or [] curve_names = cmds.keyframe(query=True, selected=True, name=True) or [] else: keys = cmds.keyframe(query=True, timeChange=True) or [] curve_names = cmds.keyframe(query=True, name=True) or [] first_key = min(keys) last_key = max(keys) mid_pivot = (first_key + last_key) / 2 for curve in curve_names: cmds.scaleKey(curve, time=(first_key, last_key), timeScale=-1.0, timePivot=mid_pivot) do_snap_keys(first_key, last_key)
def MirrorAnimation(item, optionType, scaleMatrix): attr = [ "translateX", "translateY", "translateZ", "rotateX", "rotateY", "rotateZ" ] for idx, a in enumerate(attr): if cmds.getAttr(item + '.' + a, lock=True) == False: cmds.select(cl=True) key = cmds.selectKey(item, attribute=a) if (key > 0): if optionType == option(option.keys): cmds.selectKey(item, time=(cTime, cTime), attribute=a) else: #"curve" cmds.selectKey(item, attribute=a) cmds.scaleKey(valueScale=scaleMatrix[idx], valuePivot=0.0) cmds.select(item)
def flipAnimation(nodes, *args): nodes = mc.ls(nodes, long=True) pairs = getMirrorPairs(nodes) flipSingles = [x for x in nodes if x not in pairs.keys()] #do the singles: for node in flipSingles: for axis in getMirrorAxis(node): plug = '{}.{}'.format(node, axis) mc.scaleKey(plug, attribute=axis, valueScale=-1) done = [] for node, mirror in pairs.items(): if node not in done: swapAnimation(node, mirror) done.append(mirror)
def swapAnimation(fromNode, toNode): if not mc.keyframe(fromNode, query=True, name=True): mc.cutKey(toNode, clear=True) return attrs = mc.listAttr(fromNode, keyable=True) if not attrs: return for attr in attrs: if not mc.attributeQuery(attr, node=toNode, exists=True): mc.cutKey(fromNode, attribute=attr, clear=True) continue fromPlug = '{}.{}'.format(fromNode, attr) toPlug = '{}.{}'.format(toNode, attr) srcCurve = mc.listConnections(fromPlug, source=True, destination=False, type='animCurve') dstCurve = mc.listConnections(toPlug, source=True, destination=False, type='animCurve') copySrc=None copyDst=None if srcCurve: copySrc = mc.duplicate(srcCurve[0])[0] if dstCurve: copyDst = mc.duplicate(dstCurve[0])[0] if copySrc: try: mc.cutKey(copySrc) mc.pasteKey(toNode, attribute=attr, option='replaceCompletely') except:pass if copyDst: try: mc.cutKey(copyDst) mc.pasteKey(fromNode, attribute=attr, option='replaceCompletely') except:pass for axis in getMirrorAxis(toNode): mc.scaleKey(toNode, attribute=axis, valueScale=-1) mc.scaleKey(fromNode, attribute=axis, valueScale=-1)
def scaleKey(*args, **kwargs): for flag in ['t', 'time']: try: rawVal = kwargs[flag] except KeyError: continue else: kwargs[flag] = _factories.convertTimeValues(rawVal) res = cmds.scaleKey(*args, **kwargs) return res
def mirror_x(*args): try: selected_curve_key = cmds.keyframe(query=True, selected=True) n_start = selected_curve_key[0] k_count = -1 for o_key in selected_curve_key: k_count = k_count + 1 n_end = selected_curve_key[k_count] cmds.scaleKey(scaleSpecifiedKeys=True, newStartTime=n_end, newStartFloat=n_end, newEndTime=n_start, newEndFloat=n_start) mel.eval('doBuffer snapshot') mel.eval('doBuffer swap') except: print 'Animation Key is Not Selected'
def scaleAnimation(scaleValue=1): '''if the selected object is animated, tune up or down the value on every single key ''' controls = mc.ls(sl=True) mc.undoInfo(openChunk=True) for con in controls: if isAnimCVConnected(con): keysFramesTime = mc.keyframe(con, query=True, timeChange=True) lastKeyTime = max(keysFramesTime) mc.scaleKey(con, floatPivot=0, floatScale=1, includeUpperBound=False, timePivot=0, timeScale=1, valuePivot=0, valueScale=scaleValue, time=(0, lastKeyTime + 1)) mc.undoInfo(closeChunk=True) return
def scaleCrv(val): ''' -Scale selected Graph Editor curves with given value. -Pivot derived from selection - get selected keys of curves, if values are the same, the pivot is from that position, otherwise pivot defaults to 0. ''' print '___here' # get curves of selected keys crvs = cmds.keyframe(q=True, name=True, sl=True) pvt = 0.0 if crvs is not None: if len(crvs) == 1: # keys selected from one curve selKey_1 = cmds.keyframe(crvs, q=True, vc=True, sl=True) selKey_2 = list(set(cmds.keyframe(crvs, q=True, vc=True, sl=True))) if len(selKey_1) != len(selKey_2): message('1') # multiple keys selected, same value, pivot = 0 cmds.scaleKey(crvs, vs=val, vp=pvt) elif len(selKey_1) == 1: pvt = selKey_1[0] cmds.scaleKey(crvs, vs=val, vp=pvt) message('Single key selected, pivot = ' + str(pvt)) else: cmds.scaleKey(crvs, vs=val, vp=pvt) message('Multiple keys selected from one curve, pivot = ' + str(pvt)) elif len(crvs) > 1: selKey = list(set(cmds.keyframe(crvs, q=True, vc=True, sl=True))) if len(selKey) == 1: message('More than one curve selected, pivot = ' + str(pvt)) # feature turned off # pvt = selKey[0] # message('Selected Keys from different curves have the same value, pivot = ' + str(pvt)) else: message('Selected Keys have different values, pivot = ' + str(pvt)) cmds.scaleKey(crvs, vs=val, vp=pvt) else: message('Select one or more keys in the graph editor. Pivots depend on selection.')
def curve(anim_curve, time_filter, skip_cycle=True, trim=False): if not cmds.objExists(anim_curve): print "Could not find {0}".format(anim_curve) if cmds.nodeType(anim_curve) not in ("animCurveTL", "animCurveTA", "animCurveTT", "animCurveTU",): print 'Skipping non-time-based curve {0}'.format(anim_curve) return anim_curve # If a trim hasn't been specified then treat simple retimes as # global offsets or scales. if not trim: # If the time filter is a single value pair we calculate the # offset and apply it to the entire framerange and return the # anim_curve. if len(time_filter) == 1: offset = time_filter[0][0] - time_filter[0][1] src_keys = cmds.keyframe(anim_curve, query=True) new_start = min(src_keys)+offset new_end = max(src_keys)+offset cmds.scaleKey(anim_curve, time=(min(src_keys),max(src_keys)), newStartTime=new_start, newEndTime=new_end,) return anim_curve # If there are only two values then it is a simple scale. # Calculate the scale and apply it to the entire key range. If # it is a held frame then treat it as a complex retime. if len(time_filter) == 2: new_start, src_start = time_filter[0] new_end, src_end = time_filter[1] if src_start != src_end: scale = (float(new_end) - new_start)/(src_end-src_start) offset = new_start-(src_start*scale) src_keys = cmds.keyframe(anim_curve, query=True) if not src_keys: cmds.select(anim_curve) new_start = min(src_keys)*scale+offset new_end = max(src_keys)*scale+offset cmds.scaleKey(anim_curve, time=(min(src_keys),max(src_keys)), newStartTime=new_start, newEndTime=new_end,) return anim_curve # If the curve has a cycle on it then a complex retime will be # unpredictable. So if the skip_cycle value is true we just return # the curve unchanged. pre_inf = cmds.getAttr("{0}.preInfinity".format(anim_curve)) post_inf = cmds.getAttr("{0}.postInfinity".format(anim_curve)) if pre_inf > 2 or post_inf > 2: print 'No retime applied to cycling curve {0}'.format(anim_curve) return anim_curve # Convert the remap frame pairs (old frame/new frame) into time # blocks (old start, old end, new start, new end) so we can manage # regions instead of points. time_blocks = [] floor_frame = "Initialised." for x in range(len(time_filter)-1): # Unpack the current and next time values. new_start, src_start = time_filter[x] new_end, src_end = time_filter[x+1] time_blocks.append((src_start, src_end, new_start, new_end,)) # Ensure the time blocks don't overlap. if floor_frame == "Initialised.": floor_frame = new_start if new_end <= floor_frame: cmds.error("Time filter overlaps: {0}".format(time_filter)) else: floor_frame = new_end # Add a keyframe at each remap point, if one does not already exist, # and unlock the tangents so they can be remapped independently. for frame, new_frame in time_filter: if not cmds.keyframe(anim_curve, time=(new_frame,), query=True): cmds.setKeyframe(anim_curve, insert=True, time=(new_frame,)) cmds.keyTangent(anim_curve, edit=True, time=(frame,), lock=False) # Create a temporary curve to transcribe the remap data to and a # buffer curve to hold the keys from each time block while we scale # them. node_type = cmds.nodeType(anim_curve) temp_curve = cmds.createNode(node_type, name=anim_curve+'remap_temp', skipSelect=True) # Transcribe the remapped keys onto the temporary curve using the # data in the time_blocks list. for time_block in time_blocks: src_start, src_end, new_start, new_end = time_block # If the time block uses the same source frame for the whole # time block then we need to treat it as a held frame. if src_end == src_start: # Add a duplicate key at the start and end of the time block. keys = cmds.keyframe(anim_curve, time=(src_start,), query=True) key_data = crv.key_info_by_time(anim_curve, keys[0]) key_data['key_time'] = new_end crv.add_keyframe(temp_curve, key_data) key_data['key_time'] = new_start key_data['out_type'] = 'step' key_data['out_angle'] = 0 key_data['out_weight'] = 0 crv.add_keyframe(temp_curve, key_data) # If the time block uses different source frames at the start # and end of the time block then we need to scale the region # between those frames. else: # If we're scaling backwards then shuffle the values # to work with the scaleKey script if src_start > src_end: (src_start, src_end) = (src_end, src_start) (new_start, new_end) = (new_end, new_start) reverse=True else: reverse=False # Copy those key in the time block to a buffer curve. buffer_curve = cmds.createNode(node_type, name=anim_curve+'buffer_temp', skipSelect=True) keys = cmds.keyframe(anim_curve, time=(src_start,src_end,), query=True) for key in keys: key_data = crv.key_info_by_time(anim_curve, key) crv.add_keyframe(buffer_curve, key_data) # Scale the keys on the buffer curve. cmds.scaleKey(buffer_curve, time=(src_start,src_end), newStartTime=new_start, newEndTime=new_end,) # Stepped keys break if they're reversed, so this is a fix # for that. if reverse: for key_index in range(0, len(keys)-1): if cmds.keyTangent(anim_curve, outTangentType=True, index=(key_index, key_index), query=True)[0] == 'step': new_index = len(keys)-key_index-2 cmds.keyTangent(buffer_curve, index=(new_index,), outTangentType = 'stepnext') if cmds.keyTangent(anim_curve, outTangentType=True, index=(key_index, key_index), query=True)[0] == 'stepnext': new_index = len(keys)-key_index-2 cmds.keyTangent(buffer_curve, index=(new_index,), outTangentType = 'step') # Transcribe the keys to the temp curve. buffer_keys = cmds.keyframe(buffer_curve, query=True) temp_keys = cmds.keyframe(temp_curve, query=True) for key_index in range(0, len(buffer_keys)): key_data = crv.key_info_by_index(buffer_curve, key_index) # If the start/end keys already exist on the curve we # don't want to overwrite the tangents before or after # the time block. if temp_keys and key_index == 0: if key_data['key_time'] in temp_keys: old_data = crv.key_info_by_time(temp_curve, key_data['key_time']) key_data['in_type'] = old_data['in_type'] key_data['in_angle'] = old_data['in_angle'] key_data['in_weight'] = old_data['in_weight'] if temp_keys and key_index == len(buffer_keys)-1: if key_data['key_time'] in temp_keys: old_data = crv.key_info_by_time(temp_curve, key_data['key_time']) key_data['out_type'] = old_data['out_type'] key_data['out_angle'] = old_data['out_angle'] key_data['out_weight'] = old_data['out_weight'] crv.add_keyframe(temp_curve, key_data) cmds.delete(buffer_curve) # Transfer the keys from the temp curve to the original curve. src_keys = cmds.keyframe(anim_curve, query=True) temp_keys = cmds.keyframe(temp_curve, query=True) # Add a placeholder keyframe below the range of either curve. (If # we delete all the keyframes on a curve it will delete the curve # node as well.) min_key = min(src_keys) - min(temp_keys)-1 cmds.setKeyframe(anim_curve, time=min_key, value=0, inTangentType = 'linear', outTangentType = 'linear',) # Delete all other keys on the source curve. cmds.cutKey(anim_curve, time=(min(src_keys),max(src_keys)), option='keys') # Copy the keys from the temp curve. for key in temp_keys: key_data = crv.key_info_by_time(temp_curve, key) crv.add_keyframe(anim_curve, key_data) cmds.delete(temp_curve) # Delete the placeholder key. cmds.cutKey(anim_curve, time=(min_key,), option='keys') return anim_curve
def pull(self): cmds.scaleKey(curve, index=key, valuePivot=self.pivotValue, valueScale=self.factor)
def flipAnimation(nodes, *args): nodes = mc.ls(nodes, long=True) pairs = getMirrorPairs(nodes) flipSingles = [x for x in nodes if x not in pairs.keys()] #do the singles: for node in flipSingles: for axis in getMirrorAxis(node): plug = '{}.{}'.format(node,axis) mc.scaleKey(plug, attribute=axis, valueScale=-1) done = [] for node, mirror in pairs.items(): if node not in done: swapAnimation(node, mirror) done.append(mirror) # ______________________ # - -/__ Revision History __/- - - - - - - - - - - - - - - - - - - - - - - - # # Revision 1: 2013-03-10 : First publish, fkIk switching only. # # Revision 2: 2014-02-24 : Added selection scripts, UI, and updated for latest version of Puppeteer. # # Revision 3: 2014-03-01 : adding category # # Revision 4: 2015-04-27 : First major support for puppet marking menu. # # Revision 5: 2015-04-27 : temp node clean up bug fixed. # # Revision 6: 2015-05-14 : Space switch bake bug fixed. # # Revision 7: 2015-05-18 : Minor bugfixes. # # Revision 8: 2015-06-23 : puppet context menu fix for windows paths # # Revision 9: 2015-11-18 : Updated fk ik switching code for latest puppeteer # # Revision 10: 2016-09-25 : Minor KeyError bug fix. # # Revision 11: 2017-02-08 : zero out pole twist when matching to ik # # Revision 12: 2017-02-21 : fixing stepped tangents on ik switch attribute # # Revision 13: 2017-03-28 : mirroring and visibility sets # # Revision 14: 2017-03-28 : removing hide all sets, maya not allow # # Revision 15: 2017-04-06 : Context menu bug fixes and additional features. # # Revision 16: 2017-04-23 : Space Switch context menu bug fix # # Revision 17: 2017-04-25 : FK IK switching keying update # # Revision 18: 2017-05-24 : search higher for mirrored nodes when matching # # Revision 19: 2017-06-04 : adding puppet settings attributes # # Revision 20: 2017-06-13 : space switch matching bug fix # # Revision 21: 2017-06-29 : full context menu for puppet node # # Revision 22: 2017-06-30 : proper testing for puppet # # Revision 23: 2017-07-07 : space switch and mirroring bugs # # Revision 24: 2018-02-17 : Updating license to MIT.
def FbxExport(): # coding=1251 import maya.cmds as cmds import maya.mel as mel import os import sys # задаю рабочий путь workPath = 'e:\SH8\.dialogues\\' # задаю путь, где хранятся .fbx анимации animFBXDir = 'anims_FBX\\' # задаю путь, где хранятся .ma анимации lkz trax editor clipPath = 'z:\.src\shared\chr\_face\.clips\\' # задаю путь, где хранятся юфещь анимации atomPath = 'z:/.src/shared/chr/_face/.anims_atom/' # задаю путь, где хранятся .avi, видео для просмотра и поиска анимаций animPreviewPath = 'z:/.src/shared/chr/_face/.anims_preview_database/' # задаю имя character set charSet = 'default_character' # скрываю лишние объекты в сцене, для чистоты записи .avi if cmds.objExists('imagePlane1'): cmds.hide('imagePlane1') cmds.hide('*_LOC') # создаю список из кривых, для экспорта их в .ma animCurvesList = cmds.ls(type='animCurve') # создаю список для лицевых контроллеров ctrlsList = cmds.ls('*_ctrl') # отделяю имя анимации от пути и расширенния и имени персонажа fullPathName = cmds.file(q = True, exn = True) fullPathName = fullPathName.split('/') fileName = fullPathName[-1] fileName = fileName[:-3] leftTrim = fileName.find('_') animName = fileName[(leftTrim + 1):] # отделяю имя папки диалога dialoguePath = fullPathName[-3] + '\\' dialogueDir = fullPathName[-3] animFBXPath = workPath + dialoguePath + animFBXDir # выделяю объекты, которые уйдут в експорт rkbgf .ma # сейчас выделяю все кривые, если клипов будет несколько, туда затянутся все кривые # то есть, рассчитано, с условием, что в данном файле одна анимация, clip # сжимаю анимацию в два раза, чтобы она соответствовала реальному времени cmds.select(ctrlsList) cmds.scaleKey(iub = False, ts = 0.5, tp = 1, fs = 0.5, fp = 1, vs = 1, vp = 0) # задаю новые границы timeline maxTime = (cmds.playbackOptions( q = True, maxTime = True)/2) maxTime = round(maxTime) cmds.playbackOptions(maxTime = int(maxTime)) # делаю экспорт видео для просмотра # делаю проверку на объекты, которые не подходят к названию # нужна только для старых анимаций, созданых раньше июля 2015 if cmds.objExists('eyes_CTRL'): cmds.rename('eyes_CTRL', 'eyes_ctrl') # Удаляю группу и локаторы костей языка # Временно, пока не настроил их if cmds.objExists('tongue_1_GRP'): cmds.delete('tongue_1_GRP', 'tongue_2_GRP') # создаю переменные, где храню значение начала и конца timeline currEndTime = cmds.playbackOptions( q=True, maxTime=True ) currStartTime = cmds.playbackOptions( q=True, minTime=True ) # выделяю все лицевые контроллеры cmds.select(ctrlsList) cmds.currentTime(currStartTime, edit=True) cmds.setKeyframe(ctrlsList) cmds.currentTime(currEndTime, edit=True) cmds.setKeyframe(ctrlsList) # смещаю ключи на 10 кадров вперед относительно их позиции cmds.keyframe(edit=True, relative = True, timeChange = (0 + 10)) # задаю новые границы timeline currEndTime += 20 cmds.playbackOptions( minTime=0, maxTime=currEndTime ) # создаю функцию, которая обнуляю все каналы объектов из списка def SetKeysToZero(): global ctrlsList for ctrl in ctrlsList: attrs = cmds.listAttr(ctrl, k=True) #создает список атрибутов для каждого из выделенных объектов for attr in attrs: #для каждого атрибута из списка атрибутов if attr != "visibility": #если он не называется cmds.setAttr(ctrl + "." + attr, 0) #имя объекта+точка+название атрибута равняется нулю # ставлю нулевые ключи лицевых контроллеров вначале и конце timeline cmds.currentTime(currStartTime, edit=True) SetKeysToZero() cmds.currentTime(currEndTime, edit=True) SetKeysToZero() # запекаю анимации на timeline для всех костей fullSkeletonList = cmds.ls(type = 'joint') cmds.select(fullSkeletonList) cmds.bakeResults(fullSkeletonList, t=(currStartTime,currEndTime), simulation=True, sb=1) # перевожу переменные pytjon в mel mel.eval('string $animName = `python "fileName"`;') mel.eval('string $animFBXPath = `python "animFBXPath"`;') # делаю экспорт выделенных костей в .fbx с именем файла fullSkeletonList = cmds.ls(type = 'joint') cmds.select(fullSkeletonList) mel.eval('FBXExportConstraints -v 0') mel.eval('FBXLoadExportPresetFile -f "c:/Users/user/Documents/maya/FBX/Presets/2014.1/export/AnimationOnly.fbxexportpreset"') mel.eval('FBXExport -f ($animFBXPath + $animName + ".fbx") -s')
def mirrorBipedAnim(rigNS): ''' Mirror biped body animation @param rigNS: Rig namespace. @type rigNS: str ''' # ============= # - Check Rig - # ============= if not mc.namespace(ex=rigNS): raise Exception('Rig namespace "' + rigNS + '" not found! Unable to mirror animation...') # ==================== # - Get Rig Controls - # ==================== # Body bodyA = rigNS + ':cn_bodyA_jnt' bodyB = rigNS + ':cn_bodyB_jnt' # Spine/Neck/Head spineA = rigNS + ':cn_spineA_jnt' spineB = rigNS + ':cn_spineB_jnt' spineC = rigNS + ':cn_spineC_jnt' spineBase = rigNS + ':cn_spine_base_ctrl' spineMid = rigNS + ':cn_spine_mid_ctrl' spineTop = rigNS + ':cn_spine_top_ctrl' neck = rigNS + ':cn_neckA_jnt' head = rigNS + ':cn_headA_jnt' # Arms clav = rigNS + ':SIDE_clavicleA_jnt' armFkA = rigNS + ':SIDE_arm_fkA_jnt' armFkB = rigNS + ':SIDE_arm_fkB_jnt' armIk = rigNS + ':SIDE_arm_ik_ctrl' armPv = rigNS + ':SIDE_arm_pv_ctrl' hand = rigNS + ':SIDE_handA_jnt' # Fingers fingerList = [ 'thumbA', 'thumbB', 'thumbC', 'indexA', 'indexB', 'indexC', 'indexD', 'middleA', 'middleB', 'middleC', 'middleD', 'ringA', 'ringB', 'ringC', 'ringD', 'pinkyA', 'pinkyB', 'pinkyC', 'pinkyD' ] fingers = [rigNS + ':SIDE_' + finger + '_jnt' for finger in fingerList] # Legs legFkA = rigNS + ':SIDE_leg_fkA_jnt' legFkB = rigNS + ':SIDE_leg_fkB_jnt' legIk = rigNS + ':SIDE_leg_ik_ctrl' legPv = rigNS + ':SIDE_leg_pv_ctrl' # Feet footIk = rigNS + ':SIDE_foot_ik_ctrl' toeIk = rigNS + ':SIDE_foot_toe_ctrl' footFkA = rigNS + ':foot_fkA_jnt' footFkB = rigNS + ':foot_fkB_jnt' # ==================== # - Mirror Animation - # ==================== # Body for ctrl in [bodyA, bodyB]: if mc.objExists(ctrl): mc.scaleKey(ctrl, at=['tx', 'ry', 'rz'], valueScale=-1.0, valuePivot=0.0) # Spine/Neck/Head for ctrl in [ spineA, spineB, spineC, spineBase, spineMid, spineTop, neck, head ]: if mc.objExists(ctrl): mc.scaleKey(ctrl, at=['tz', 'rx', 'ry'], valueScale=-1.0, valuePivot=0.0) # Arms - FK (Clavicle,Arm,Hand) for ctrl in [clav, armFkA, armFkB, hand]: # Get Left/Right Nodes lfCtrl = ctrl.replace('SIDE', 'lf') rtCtrl = ctrl.replace('SIDE', 'rt') if mc.objExists(lfCtrl) and mc.objExists(rtCtrl): # Swap Left <> Right swapAnim(lfCtrl, rtCtrl) # Scale Keys mc.scaleKey(lfCtrl, at=['tx', 'ty', 'tz'], valueScale=-1.0, valuePivot=0.0) mc.scaleKey(rtCtrl, at=['tx', 'ty', 'tz'], valueScale=-1.0, valuePivot=0.0) # Arms - IK for ctrl in [armIk, armPv]: # Get Left/Right Nodes lfCtrl = ctrl.replace('SIDE', 'lf') rtCtrl = ctrl.replace('SIDE', 'rt') if mc.objExists(lfCtrl) and mc.objExists(rtCtrl): # Swap Left <> Right swapAnim(lfCtrl, rtCtrl) # Scale Keys mc.scaleKey(lfCtrl, at=['tx', 'ry', 'rz'], valueScale=-1.0, valuePivot=0.0) mc.scaleKey(rtCtrl, at=['tx', 'ry', 'rz'], valueScale=-1.0, valuePivot=0.0) # Fingers for ctrl in fingers: # Get Left/Right Nodes lfCtrl = ctrl.replace('SIDE', 'lf') rtCtrl = ctrl.replace('SIDE', 'rt') if mc.objExists(lfCtrl) and mc.objExists(rtCtrl): # Swap Left <> Right swapAnim(lfCtrl, rtCtrl) # Scale Keys mc.scaleKey(lfCtrl, at=['tx', 'ty', 'tz'], valueScale=-1.0, valuePivot=0.0) mc.scaleKey(rtCtrl, at=['tx', 'ty', 'tz'], valueScale=-1.0, valuePivot=0.0) # Legs - FK for ctrl in [legFkA, legFkB, footFkA, footFkB]: # Get Left/Right Nodes lfCtrl = ctrl.replace('SIDE', 'lf') rtCtrl = ctrl.replace('SIDE', 'rt') if mc.objExists(lfCtrl) and mc.objExists(rtCtrl): # Swap Left <> Right swapAnim(lfCtrl, rtCtrl) # Scale Keys mc.scaleKey(lfCtrl, at=['tx', 'ty', 'tz'], valueScale=-1.0, valuePivot=0.0) mc.scaleKey(rtCtrl, at=['tx', 'ty', 'tz'], valueScale=-1.0, valuePivot=0.0) # Legs - IK for ctrl in [legIk, legPv]: # Get Left/Right Nodes lfCtrl = ctrl.replace('SIDE', 'lf') rtCtrl = ctrl.replace('SIDE', 'rt') if mc.objExists(lfCtrl) and mc.objExists(rtCtrl): # Swap Left <> Right swapAnim(lfCtrl, rtCtrl) # Scale Keys mc.scaleKey(lfCtrl, at=['tx', 'ry', 'rz'], valueScale=-1.0, valuePivot=0.0) mc.scaleKey(rtCtrl, at=['tx', 'ry', 'rz'], valueScale=-1.0, valuePivot=0.0) # Feet - IK for ctrl in [footIk, toeIk]: # Get Left/Right Nodes lfCtrl = ctrl.replace('SIDE', 'lf') rtCtrl = ctrl.replace('SIDE', 'rt') if mc.objExists(lfCtrl) and mc.objExists(rtCtrl): # Swap Left <> Right swapAnim(lfCtrl, rtCtrl) # Scale Keys mc.scaleKey(lfCtrl, at=['tx', 'ry', 'rz'], valueScale=-1.0, valuePivot=0.0) mc.scaleKey(rtCtrl, at=['tx', 'ry', 'rz'], valueScale=-1.0, valuePivot=0.0)
def slow_in_slow_out(raw_anim_curves,skip, factor,controller,controllerState): """ Author: Sarah Phillips Processes animation curves and introduces Slow-In Slow-Out effects args: raw_anim_curves (dict): dict object containing keyframes of each animation curve skip (int): value that determines how many sections of the curve will not be processed controller (str): name of the animation curve that will be used as the controlling curve controllerState (bool): the state of the Controller Curve checkbox returns: Processed animation curve data rtype: dict """ if raw_anim_curves is None: cmds.headsUpMessage("No animation keys/curve selected! Select keys to filter, please!") cmds.warning("No animation keys/curve selected! Select keys to filter, please!") return filtered_curves = {} for curve_key in raw_anim_curves.keys(): curve = raw_anim_curves[curve_key] curve_length = len(curve.keys()) ys = [] xs = curve.keys() xs.sort() for x in xs: ys.append(curve[x]) first_x = xs[0] last_x =xs[-1] stationary_points = [] #check if the Controller Curve checkbox is checked if controllerState is False: curve_name = curve_key else: curve_name = controller #find the slopes of the tangents for each frame on the curve tangents = cmds.keyTangent(curve_name,q=1,oa=True,t=(first_x,last_x)) for t,x in zip(tangents,xs): #if the slope of the tangent is 0: #add the frame value to list of SPs if round(t) == 0: stationary_points.append(x) #skip the curve if there is only one or no points or the entire curve is constant number_sps = len(stationary_points) if number_sps < 2 or number_sps == curve_length: filtered_curves[curve_key] = curve continue #discard any clusters of stationary points reduced_sps = [] neighbours = [] for i in range(number_sps): current = stationary_points[i] #track neighbouring points and add only the middle value if current+1 in stationary_points or current-1 in stationary_points: neighbours.append(current) if current+1 not in stationary_points: middle = int(len(neighbours)/2) reduced_sps.append(neighbours[middle]) neighbours = [] continue reduced_sps.append(current) i=0 while i+1 < len(reduced_sps): current_tp = reduced_sps[i] next_tp = reduced_sps[i+1] cmds.selectKey(cl=True) #get tangents of all points between current_tp and next_tp cmds.selectKey(curve_key,k=True,add=True,t=(current_tp+1,next_tp-1)) slopes = cmds.keyTangent(curve_name,q=1,ia=True,t=(current_tp+1,next_tp-1)) if slopes is None: continue points = range(current_tp+1,next_tp) steepest=0 ##loop to find the steepest points between the SPs for t,x in zip(slopes,points): #if the slope is decreasing avg = sum(slopes)/len(slopes) if avg<0: steepest = min(slopes) #else if slope is increasing elif avg>0: steepest = max(slopes) sum_of_steepest_frames = 0 count = 0 steepest_rounded = steepest for k in range(0,len(slopes)): if slopes[k] == steepest_rounded: sum_of_steepest_frames +=points[k] count+=1 if count == 0: i+=1+int(skip) continue else: steepest = int(sum_of_steepest_frames/count) #perform the scale operation cmds.scaleKey(curve_key,ssk=1,autoSnap=0,t=(current_tp+1,next_tp),shape=1,iub=False,ts=factor,tp=steepest,fs=factor,fp=steepest,vs=1,vp=0) i+=1+int(skip)
cmds.select('*_ctrl') addTime = int(currStartTime)*-1 cmds.keyframe(edit=True, relative = True, timeChange = (0 + addTime)) currEndTime = currEndTime + addTime cmds.playbackOptions( minTime = 0, maxTime = currEndTime) currStartTime = cmds.playbackOptions( q=True, minTime=True ) cmds.select('*_ctrl') cmds.currentTime(currStartTime, edit=True) cmds.setKeyframe('*_ctrl') cmds.currentTime(currEndTime, edit=True) cmds.setKeyframe('*_ctrl') # сжимаю анимацию в два раза, чтобы она соответствовала реальному времени cmds.select('*_ctrl') cmds.scaleKey(iub = False, ts = 0.5, tp = 1, fs = 0.5, fp = 1, vs = 1, vp = 0) currStartTime = cmds.playbackOptions( q=True, minTime=True ) endTimeScaled = round(currEndTime/2) cmds.playbackOptions(maxTime = int(endTimeScaled)) animAmplPath = 'z:\.src\shared\chr\_face\chr_anim_amplitude_list.txt' animAmplFile = open(animAmplPath,'r') animAmplFile.close chrNameList = animMB.split('_') chrName = chrNameList[0] perscVal = None for line in animAmplFile.readlines():
def scale_values(self, scale, pivot): cmds.scaleKey(self.path, valueScale=scale, valuePivot=pivot)
def excute( startFrame ): sels = cmds.ls( '*:ctl' ) animCurves = cmds.listConnections( sels, type='animCurve' ) cmds.delete( animCurves ) timeLength = 1.7 timeList = [startFrame, timeLength+startFrame] timeList2 = [(timeLength)*0.5+startFrame, timeLength+startFrame] valueList = [0.0, startFrame] valueList2 = [0.0, 0.5] rotTimeList = [startFrame, (timeLength)*0.1+startFrame, timeLength*0.7+startFrame] rotXValueList = [0.0, 1.0, 0.0] rotZValueList = [0.0, 1.3, 0.0] distanceLength = 60.0 stretchTimeLength = 10 distMult = stretchTimeLength / distanceLength rotSize = 1.5 addTimeMult = 0.5 timePowRate = 3.0 selgoKeys = [] for sel in sels: goPiv = sel.replace( 'ctl', 'goPiv' ) dist = math.fabs( cmds.getAttr( goPiv+'.ty' ) ) addTime = dist * distMult addTime = ( addTime/stretchTimeLength )**timePowRate * stretchTimeLength multValue = addTime*rotSize*random.uniform( -1.0, 1.0 ) plusMinus = random.uniform( -1, 1 ) if plusMinus < 0: pass#multValue *= -0.0 addTime *= random.uniform( 0.95, 1.05 ) for i in range( 2 ): cmds.setKeyframe( sel+'.go', t=timeList[i]+addTime, v=valueList[i] ) cmds.setKeyframe( sel+'.change', t=timeList2[i]+addTime, v=valueList2[i] ) cmds.scaleKey( sel+'.go', tp= timeList[0]+addTime, ts=(1+addTime*addTimeMult), vp=0, vs=1 ) cmds.scaleKey( sel+'.change', tp= timeList[0]+addTime, ts=(1+addTime*addTimeMult), vp=0, vs=1 ) endTime = cmds.keyframe( sel+'.go', q=1, tc=1 )[-1] cmds.keyTangent( sel+'.go', itt='spline', ott='spline' ) cmds.setKeyframe( sel+'.change', t=endTime+0, v=valueList2[1] ) cmds.setKeyframe( sel+'.change', t=endTime+1, v=1 ) for i in range( 3 ): cmds.setKeyframe( sel+'.rotX', t=rotTimeList[i]+addTime, v=rotXValueList[i]*multValue ) cmds.setKeyframe( sel+'.rotZ', t=rotTimeList[i]+addTime, v=rotZValueList[i]*multValue ) cmds.scaleKey( sel+'.rotX', tp= rotTimeList[0]+addTime, ts=(1+addTime*addTimeMult), vp=0, vs=1 ) cmds.scaleKey( sel+'.rotZ', tp= rotTimeList[0]+addTime, ts=(1+addTime*addTimeMult), vp=0, vs=1 ) cmds.keyTangent( sel+'.rotX', itt='spline', ott='spline' ) cmds.keyTangent( sel+'.rotZ', itt='spline', ott='spline' ) selgoKeys += cmds.listConnections( sel+'.go', s=1, d=0, type='animCurve' ) cmds.select( selgoKeys )
def mirrorBipedAnim(rigNS): """ Mirror biped body animation @param rigNS: Rig namespace. @type rigNS: str """ # ============= # - Check Rig - # ============= if not cmds.namespace(ex=rigNS): raise Exception('Rig namespace "' + rigNS + '" not found! Unable to mirror animation...') # ==================== # - Get Rig Controls - # ==================== # Body bodyA = rigNS + ':cn_bodyA_jnt' bodyB = rigNS + ':cn_bodyB_jnt' # Spine/Neck/Head spineA = rigNS + ':cn_spineA_jnt' spineB = rigNS + ':cn_spineB_jnt' spineC = rigNS + ':cn_spineC_jnt' spineBase = rigNS + ':cn_spine_base_ctrl' spineMid = rigNS + ':cn_spine_mid_ctrl' spineTop = rigNS + ':cn_spine_top_ctrl' neck = rigNS + ':cn_neckA_jnt' head = rigNS + ':cn_headA_jnt' # Arms clav = rigNS + ':SIDE_clavicleA_jnt' armFkA = rigNS + ':SIDE_arm_fkA_jnt' armFkB = rigNS + ':SIDE_arm_fkB_jnt' armIk = rigNS + ':SIDE_arm_ik_ctrl' armPv = rigNS + ':SIDE_arm_pv_ctrl' hand = rigNS + ':SIDE_handA_jnt' # Fingers fingerList = ['thumbA', 'thumbB', 'thumbC', 'indexA', 'indexB', 'indexC', 'indexD', 'middleA', 'middleB', 'middleC', 'middleD', 'ringA', 'ringB', 'ringC', 'ringD', 'pinkyA', 'pinkyB', 'pinkyC', 'pinkyD'] fingers = [rigNS + ':SIDE_' + finger + '_jnt' for finger in fingerList] # Legs legFkA = rigNS + ':SIDE_leg_fkA_jnt' legFkB = rigNS + ':SIDE_leg_fkB_jnt' legIk = rigNS + ':SIDE_leg_ik_ctrl' legPv = rigNS + ':SIDE_leg_pv_ctrl' # Feet footIk = rigNS + ':SIDE_foot_ik_ctrl' toeIk = rigNS + ':SIDE_foot_toe_ctrl' footFkA = rigNS + ':foot_fkA_jnt' footFkB = rigNS + ':foot_fkB_jnt' # ==================== # - Mirror Animation - # ==================== # Body for ctrl in [bodyA, bodyB]: if cmds.objExists(ctrl): cmds.scaleKey(ctrl, at=['tx', 'ry', 'rz'], valueScale=-1.0, valuePivot=0.0) # Spine/Neck/Head for ctrl in [spineA, spineB, spineC, spineBase, spineMid, spineTop, neck, head]: if cmds.objExists(ctrl): cmds.scaleKey(ctrl, at=['tz', 'rx', 'ry'], valueScale=-1.0, valuePivot=0.0) # Arms - FK (Clavicle,Arm,Hand) for ctrl in [clav, armFkA, armFkB, hand]: # Get Left/Right Nodes lfCtrl = ctrl.replace('SIDE', 'lf') rtCtrl = ctrl.replace('SIDE', 'rt') if cmds.objExists(lfCtrl) and cmds.objExists(rtCtrl): # Swap Left <> Right swapAnim(lfCtrl, rtCtrl) # Scale Keys cmds.scaleKey(lfCtrl, at=['tx', 'ty', 'tz'], valueScale=-1.0, valuePivot=0.0) cmds.scaleKey(rtCtrl, at=['tx', 'ty', 'tz'], valueScale=-1.0, valuePivot=0.0) # Arms - IK for ctrl in [armIk, armPv]: # Get Left/Right Nodes lfCtrl = ctrl.replace('SIDE', 'lf') rtCtrl = ctrl.replace('SIDE', 'rt') if cmds.objExists(lfCtrl) and cmds.objExists(rtCtrl): # Swap Left <> Right swapAnim(lfCtrl, rtCtrl) # Scale Keys cmds.scaleKey(lfCtrl, at=['tx', 'ry', 'rz'], valueScale=-1.0, valuePivot=0.0) cmds.scaleKey(rtCtrl, at=['tx', 'ry', 'rz'], valueScale=-1.0, valuePivot=0.0) # Fingers for ctrl in fingers: # Get Left/Right Nodes lfCtrl = ctrl.replace('SIDE', 'lf') rtCtrl = ctrl.replace('SIDE', 'rt') if cmds.objExists(lfCtrl) and cmds.objExists(rtCtrl): # Swap Left <> Right swapAnim(lfCtrl, rtCtrl) # Scale Keys cmds.scaleKey(lfCtrl, at=['tx', 'ty', 'tz'], valueScale=-1.0, valuePivot=0.0) cmds.scaleKey(rtCtrl, at=['tx', 'ty', 'tz'], valueScale=-1.0, valuePivot=0.0) # Legs - FK for ctrl in [legFkA, legFkB, footFkA, footFkB]: # Get Left/Right Nodes lfCtrl = ctrl.replace('SIDE', 'lf') rtCtrl = ctrl.replace('SIDE', 'rt') if cmds.objExists(lfCtrl) and cmds.objExists(rtCtrl): # Swap Left <> Right swapAnim(lfCtrl, rtCtrl) # Scale Keys cmds.scaleKey(lfCtrl, at=['tx', 'ty', 'tz'], valueScale=-1.0, valuePivot=0.0) cmds.scaleKey(rtCtrl, at=['tx', 'ty', 'tz'], valueScale=-1.0, valuePivot=0.0) # Legs - IK for ctrl in [legIk, legPv]: # Get Left/Right Nodes lfCtrl = ctrl.replace('SIDE', 'lf') rtCtrl = ctrl.replace('SIDE', 'rt') if cmds.objExists(lfCtrl) and cmds.objExists(rtCtrl): # Swap Left <> Right swapAnim(lfCtrl, rtCtrl) # Scale Keys cmds.scaleKey(lfCtrl, at=['tx', 'ry', 'rz'], valueScale=-1.0, valuePivot=0.0) cmds.scaleKey(rtCtrl, at=['tx', 'ry', 'rz'], valueScale=-1.0, valuePivot=0.0) # Feet - IK for ctrl in [footIk, toeIk]: # Get Left/Right Nodes lfCtrl = ctrl.replace('SIDE', 'lf') rtCtrl = ctrl.replace('SIDE', 'rt') if cmds.objExists(lfCtrl) and cmds.objExists(rtCtrl): # Swap Left <> Right swapAnim(lfCtrl, rtCtrl) # Scale Keys cmds.scaleKey(lfCtrl, at=['tx', 'ry', 'rz'], valueScale=-1.0, valuePivot=0.0) cmds.scaleKey(rtCtrl, at=['tx', 'ry', 'rz'], valueScale=-1.0, valuePivot=0.0)
def mirrorBipedMocap(rigNS): """ Mirror biped body mocap animation @param rigNS: Rig namespace. @type rigNS: str """ # ============= # - Check Rig - # ============= if not cmds.namespace(ex=rigNS): raise Exception('Rig namespace "' + rigNS + '" not found! Unable to mirror animation...') # ==================== # - Get Rig Controls - # ==================== # Body body = rigNS + ':Hips' # Spine/Neck/Head spine = rigNS + ':Spine' neck = rigNS + ':Neck' head = rigNS + ':Head' # Arms clav = rigNS + ':SIDEShoulder' arm = rigNS + ':SIDEArm' foreArm = rigNS + ':SIDEForeArm' # Hand hand = rigNS + ':SIDEHand' thumb = rigNS + ':SIDEHandThumb' index = rigNS + ':SIDEHandIndex' middle = rigNS + ':SIDEHandMiddle' ring = rigNS + ':SIDEHandRing' pinky = rigNS + ':SIDEHandPinky' finger = [thumb, index, middle, ring, pinky] # Legs upLeg = rigNS + ':SIDEUpLeg' leg = rigNS + ':SIDELeg' # Foot foot = rigNS + ':SIDEFoot' toe = rigNS + ':SIDEToeBase' # Roll roll = 'Roll' # Side left = 'Left' right = 'Right' # ==================== # - Mirror Animation - # ==================== # Body for ctrl in [body]: if cmds.objExists(ctrl): cmds.scaleKey(ctrl, at=['tx', 'ry', 'rz'], valueScale=-1.0, valuePivot=0.0) # Spine/Neck/Head for item in [spine, neck, head]: ind = '' while cmds.objExists(item + str(ind)): ctrl = item + str(ind) cmds.scaleKey(ctrl, at=['rx', 'ry'], valueScale=-1.0, valuePivot=0.0) if not ind: ind = 0 ind += 1 # Shoulder for ctrl in [clav]: # Get Left/Right Nodes lfCtrl = ctrl.replace('SIDE', left) rtCtrl = ctrl.replace('SIDE', right) if cmds.objExists(lfCtrl) and cmds.objExists(rtCtrl): swapAnim(lfCtrl, rtCtrl) cmds.scaleKey(lfCtrl, at=['tz'], valueScale=-1.0, valuePivot=0.0) cmds.scaleKey(rtCtrl, at=['tz'], valueScale=-1.0, valuePivot=0.0) # Arms for ctrl in [arm, foreArm, hand]: # Get Left/Right Nodes lfCtrl = ctrl.replace('SIDE', left) rtCtrl = ctrl.replace('SIDE', right) if cmds.objExists(lfCtrl) and cmds.objExists(rtCtrl): swapAnim(lfCtrl, rtCtrl) cmds.scaleKey(lfCtrl, at=['tx', 'ty', 'tz'], valueScale=-1.0, valuePivot=0.0) cmds.scaleKey(rtCtrl, at=['tx', 'ty', 'tz'], valueScale=-1.0, valuePivot=0.0) # Get Roll Nodes lfCtrl = lfCtrl + roll rtCtrl = rtCtrl + roll if cmds.objExists(lfCtrl) and cmds.objExists(rtCtrl): swapAnim(lfCtrl, rtCtrl) cmds.scaleKey(lfCtrl, at=['tx', 'ty', 'tz'], valueScale=-1.0, valuePivot=0.0) cmds.scaleKey(rtCtrl, at=['tx', 'ty', 'tz'], valueScale=-1.0, valuePivot=0.0) # Fingers for ctrl in finger: # Get Left/Right Nodes lfCtrl = ctrl.replace('SIDE', left) rtCtrl = ctrl.replace('SIDE', right) ind = 1 while cmds.objExists(lfCtrl + str(ind)) and cmds.objExists(rtCtrl + str(ind)): lfCtrlInd = lfCtrl + str(ind) rtCtrlInd = rtCtrl + str(ind) swapAnim(lfCtrlInd, rtCtrlInd) cmds.scaleKey(lfCtrlInd, at=['tx', 'ty', 'tz'], valueScale=-1.0, valuePivot=0.0) cmds.scaleKey(rtCtrlInd, at=['tx', 'ty', 'tz'], valueScale=-1.0, valuePivot=0.0) if not ind: ind = 0 ind += 1 # Legs for ctrl in [upLeg, leg, foot, toe]: # Get Left/Right Nodes lfCtrl = ctrl.replace('SIDE', left) rtCtrl = ctrl.replace('SIDE', right) if cmds.objExists(lfCtrl) and cmds.objExists(rtCtrl): swapAnim(lfCtrl, rtCtrl) cmds.scaleKey(lfCtrl, at=['tx', 'ty', 'tz'], valueScale=-1.0, valuePivot=0.0) cmds.scaleKey(rtCtrl, at=['tx', 'ty', 'tz'], valueScale=-1.0, valuePivot=0.0) # Get Roll Nodes lfCtrl = lfCtrl + roll rtCtrl = rtCtrl + roll if cmds.objExists(lfCtrl) and cmds.objExists(rtCtrl): swapAnim(lfCtrl, rtCtrl) cmds.scaleKey(lfCtrl, at=['tx', 'ty', 'tz'], valueScale=-1.0, valuePivot=0.0) cmds.scaleKey(rtCtrl, at=['tx', 'ty', 'tz'], valueScale=-1.0, valuePivot=0.0)
def pull(self): cmds.scaleKey( curve, index=key, valuePivot=self.pivotValue, valueScale=self.factor)
def BatchAnimExport(): ''' алгоритм работы скрипта, который создает ref позы для персонажей проверяет, существует ли ref .fbx если да копирует .fbx в работу папку если нет создает .fbx копирует в рабочую папку ''' # coding=1251 import maya.cmds as cmds import maya.mel as mel import os import re import sys # вызываю окно, куда вписываю имя рабочей папки, 'case_dialogue' result = cmds.promptDialog( title='working dir name', message='add working dir', button=['OK', 'Cancel'], defaultButton='OK', cancelButton='Cancel', dismissString='Cancel') if result == 'OK': workingName = cmds.promptDialog(query=True, text=True) workingDirName = workingName.upper() + '\\' if result == 'Cancel': sys.exit('Cancelled') # задаю рабочий каталог workDirPath = 'e:\SH8\.dialogues\\' # задаю рабочий каталог для настроеных персонажей animChrPath = 'e:\SH8\.dialogues\.crhs\\' # задаю рабочий каталог для настроеных персонажей refFbxDir = 'e:\SH8\.dialogues\.crhs\.fbx_ref\\' # задаю путь, где хранятся .fbx анимации animFBXDir = 'anims_FBX\\' # задаю путь, где хранятся .fbx анимации animMBDir = 'anims_MB\\' # задаю приставку для названия ref анимаций refPrefix = '_face_10_fr_ref.fbx' log = '\n---------- export log:----------\n' # папкарабочего диалога animListDir = workDirPath + workingDirName # путь к файлу, где содержится список анимаций animListName = animListDir + workingName + '_anim_list.txt' # путь к папке .fbx анимаций рабочего диалога animFBXPath = workDirPath + workingDirName + animFBXDir # путь к папке .mb анимаций рабочего диалога animMBPath = workDirPath + workingDirName + animMBDir # составляю список из файлов, настроеных chr templates chrMBList = cmds.getFileList(fs = '*.mb', fld = animChrPath) # составляю список из файлов, .fbx ref анимаций chr templates refAnimList = cmds.getFileList(fs = '*.fbx', fld = refFbxDir) # составляю список из файлов, .fbx ref анимаций chr templates animMBList = cmds.getFileList(fs = '*.mb', fld = animMBPath) # создаю список для лицевых контроллеров ctrlsList = cmds.ls('*_ctrl') # получаю длину списка анимаций для проверки кол-ва выполненых действий animListForLen = open(animListName,'r') animLenLines = animListForLen.readlines() animListLen = len(animLenLines) animListForLen.close() # функция, которая определяет, какие персонажи используются в диалоге по anim_list.txt и списку chr templates def CompareLists(searchInList, searchForList): searchList = '' for searchInString in searchInList: for searchForString in searchForList: searchForString = searchForString.split('.') if searchForString[0].lower() in searchInString: if not searchForString[0].lower() in searchList: if searchList == '': searchList += searchForString[0].lower() else: searchList += ' ' + searchForString[0].lower() return searchList # сохраняю результат в переменную crhsInDialogue = CompareLists(animLenLines, chrMBList) # копирую в рабочу .fbx папку .fbx ref anims for chr in crhsInDialogue.split(' '): if os.path.exists(refFbxDir + chr + refPrefix): cmds.sysFile(refFbxDir + chr + refPrefix, cp = animFBXPath + chr + refPrefix) # если .fbx ref anim не сущетсвует, создаю его if not os.path.exists(refFbxDir + chr + refPrefix): cmds.file(animChrPath + chr + '.mb', o = True, f = True) # запекаю анимации на timeline для всех костей fullSkeletonList = cmds.ls(type = 'joint') cmds.select(fullSkeletonList) cmds.cutKey() cmds.bakeResults(fullSkeletonList, t=(0,10), simulation=True, sb=1) # делаю экспорт выделенных костей в .fbx с именем файла cmds.select(fullSkeletonList) mel.eval('string $refFbxDir = `python "refFbxDir"`;') mel.eval('string $chrName = `python "chr"`;') mel.eval('string $refPrefix = `python "refPrefix"`;') mel.eval('FBXExportConstraints -v 0') mel.eval('FBXLoadExportPresetFile -f "c:/Users/user/Documents/maya/FBX/Presets/2014.1/export/AnimationOnly.fbxexportpreset"') mel.eval('FBXExport -f ($refFbxDir + $chrName + $refPrefix) -s') cmds.sysFile(refFbxDir + chr + refPrefix, cp = animFBXPath + chr + refPrefix) # export animation for animMB in animMBList: if '_face_' in animMB: animFBX = animMB[:-3] if not os.path.exists(animFBXPath + animFBX + '.fbx'): cmds.file(animMBPath + animMB, o = True, f = True) # отделяю имя анимации от пути и расширенния и имени персонажа fullPathName = cmds.file(q = True, exn = True) fullPathName = fullPathName.split('/') fileName = fullPathName[-1] fileName = fileName[:-3] # создаю переменные, где храню значение начала и конца timeline currEndTime = cmds.playbackOptions( q=True, maxTime=True ) currStartTime = cmds.playbackOptions( q=True, minTime=True ) endTimeScaled = round(currEndTime/2) cmds.select('*_ctrl') cmds.currentTime(currStartTime, edit=True) cmds.setKeyframe('*_ctrl') cmds.currentTime(currEndTime, edit=True) cmds.setKeyframe('*_ctrl') # сжимаю анимацию в два раза, чтобы она соответствовала реальному времени cmds.select('*_ctrl') cmds.scaleKey(iub = False, ts = 0.5, tp = 1, fs = 0.5, fp = 1, vs = 1, vp = 0) cmds.playbackOptions(maxTime = int(endTimeScaled)) # Удаляю группу и локаторы костей языка # Временно, пока не настроил их if cmds.objExists('tongue_1_GRP'): cmds.delete('tongue_1_GRP', 'tongue_2_GRP') # выделяю все лицевые контроллеры cmds.select('*_ctrl') # смещаю ключи на 10 кадров вперед относительно их позиции cmds.keyframe(edit=True, relative = True, timeChange = (0 + 10)) # задаю новые границы timeline currEndTime = cmds.playbackOptions( q=True, maxTime=True ) currEndTime += 20 cmds.playbackOptions( minTime=0, maxTime=currEndTime ) # создаю функцию, которая обнуляю все каналы объектов из списка def SetKeysToZero(): cmds.select('*_ctrl') ctrlsList = cmds.ls(sl = True) for ctrl in ctrlsList: attrs = cmds.listAttr(ctrl, k=True) #создает список атрибутов для каждого из выделенных объектов for attr in attrs: #для каждого атрибута из списка атрибутов if attr != "visibility": #если он не называется cmds.setAttr(ctrl + "." + attr, 0) #имя объекта+точка+название атрибута равняется нулю # ставлю нулевые ключи лицевых контроллеров вначале и конце timeline cmds.currentTime(currStartTime, edit=True) SetKeysToZero() cmds.currentTime(currEndTime, edit=True) SetKeysToZero() # запекаю анимации на timeline для всех костей fullSkeletonList = cmds.ls(type = 'joint') cmds.select(fullSkeletonList) cmds.bakeResults(fullSkeletonList, t=(currStartTime,currEndTime), simulation=True, sb=1) # перевожу переменные pytjon в mel mel.eval('string $animName = `python "fileName"`;') mel.eval('string $animFBXPath = `python "animFBXPath"`;') # делаю экспорт выделенных костей в .fbx с именем файла fullSkeletonList = cmds.ls(type = 'joint') cmds.select(fullSkeletonList) mel.eval('FBXExportConstraints -v 0') mel.eval('FBXLoadExportPresetFile -f "c:/Users/user/Documents/maya/FBX/Presets/2014.1/export/AnimationOnly.fbxexportpreset"') mel.eval('FBXExport -f ($animFBXPath + $animName + ".fbx") -s') # создаю лог работы if os.path.exists(animFBXPath + fileName + '.fbx'): log += fileName + '.fbx exported \n' else: log += fileName + '.fbx NOT exported \n' print log
def flip(): keys = mc.keyframe(q=1) pivot_key = (min(keys) + max(keys)) / 2.0 mc.scaleKey(iub=False, ts=-1, tp=pivot_key, animation='keys')
def expand(): lastValue = mc.keyframe(q=1, lastSelected=1, vc=1) mc.scaleKey(vs=1.1, vp=lastValue[0])
def keys_editor_func(option, piv): keyCount = cmds.keyframe(q=True, sl=True, kc=True) if keyCount == 0: return cmds.undoInfo(openChunk=True, chunkName="keys_editor_func") if option == "push": scaleValue = 1 / 0.9 elif option == "pull": scaleValue = 0.9 elif option == "neg": scaleValue = -1 elif option == "offset": pass else: cmds.undoInfo(closeChunk=True, chunkName="keys_editor_func") return selectedCurves = cmds.keyframe(q=True, n=True, sl=True) for crv in selectedCurves: timeArray = cmds.keyframe(crv, q=True, tc=True, sl=True) if piv == "left": pivTime = cmds.findKeyframe(crv, which="previous", time=(timeArray[0], timeArray[0])) keyValue = cmds.keyframe(crv, q=True, time=(timeArray[0], timeArray[0]), vc=True)[0] pivValue = cmds.keyframe(crv, q=True, time=(pivTime, pivTime), vc=True)[0] elif piv == "right": pivTime = cmds.findKeyframe(crv, which="next", time=(timeArray[-1], timeArray[-1])) keyValue = cmds.keyframe(crv, q=True, time=(timeArray[-1], timeArray[-1]), vc=True)[0] pivValue = cmds.keyframe(crv, q=True, time=(pivTime, pivTime), vc=True)[0] elif piv == "avg": keyValues = cmds.keyframe(crv, q=True, sl=True, vc=True) pivValue = (max(keyValues) + min(keyValues)) / 2 else: break selectedValues = cmds.keyframe(crv, q=True, iv=True, sl=True) if option == "offset": offsetValue = pivValue - keyValue for slv in selectedValues: cmds.keyframe(crv, relative=True, index=(slv, slv), vc=offsetValue) else: for slv in selectedValues: cmds.scaleKey(crv, index=(slv, slv), vp=pivValue, vs=scaleValue) cmds.undoInfo(closeChunk=True, chunkName="keys_editor_func")
def copyAnimation(fromNode, toNode): mc.copyKey(fromNode) mc.pasteKey(toNode, option='replaceCompletely') for axis in getMirrorAxis(toNode): mc.scaleKey(toNode, attribute=axis, valueScale=-1)
def mirrorBipedMocap(rigNS): ''' Mirror biped body mocap animation @param rigNS: Rig namespace. @type rigNS: str ''' # ============= # - Check Rig - # ============= if not mc.namespace(ex=rigNS): raise Exception('Rig namespace "' + rigNS + '" not found! Unable to mirror animation...') # ==================== # - Get Rig Controls - # ==================== # Body body = rigNS + ':Hips' # Spine/Neck/Head spine = rigNS + ':Spine' neck = rigNS + ':Neck' head = rigNS + ':Head' # Arms clav = rigNS + ':SIDEShoulder' arm = rigNS + ':SIDEArm' foreArm = rigNS + ':SIDEForeArm' # Hand hand = rigNS + ':SIDEHand' thumb = rigNS + ':SIDEHandThumb' index = rigNS + ':SIDEHandIndex' middle = rigNS + ':SIDEHandMiddle' ring = rigNS + ':SIDEHandRing' pinky = rigNS + ':SIDEHandPinky' finger = [thumb, index, middle, ring, pinky] # Legs upLeg = rigNS + ':SIDEUpLeg' leg = rigNS + ':SIDELeg' # Foot foot = rigNS + ':SIDEFoot' toe = rigNS + ':SIDEToeBase' # Roll roll = 'Roll' # Side left = 'Left' right = 'Right' # ==================== # - Mirror Animation - # ==================== # Body for ctrl in [body]: if mc.objExists(ctrl): mc.scaleKey(ctrl, at=['tx', 'ry', 'rz'], valueScale=-1.0, valuePivot=0.0) # Spine/Neck/Head for item in [spine, neck, head]: ind = '' while mc.objExists(item + str(ind)): ctrl = item + str(ind) mc.scaleKey(ctrl, at=['rx', 'ry'], valueScale=-1.0, valuePivot=0.0) if not ind: ind = 0 ind += 1 # Shoulder for ctrl in [clav]: # Get Left/Right Nodes lfCtrl = ctrl.replace('SIDE', left) rtCtrl = ctrl.replace('SIDE', right) if mc.objExists(lfCtrl) and mc.objExists(rtCtrl): swapAnim(lfCtrl, rtCtrl) mc.scaleKey(lfCtrl, at=['tz'], valueScale=-1.0, valuePivot=0.0) mc.scaleKey(rtCtrl, at=['tz'], valueScale=-1.0, valuePivot=0.0) # Arms for ctrl in [arm, foreArm, hand]: # Get Left/Right Nodes lfCtrl = ctrl.replace('SIDE', left) rtCtrl = ctrl.replace('SIDE', right) if mc.objExists(lfCtrl) and mc.objExists(rtCtrl): swapAnim(lfCtrl, rtCtrl) mc.scaleKey(lfCtrl, at=['tx', 'ty', 'tz'], valueScale=-1.0, valuePivot=0.0) mc.scaleKey(rtCtrl, at=['tx', 'ty', 'tz'], valueScale=-1.0, valuePivot=0.0) # Get Roll Nodes lfCtrl = lfCtrl + roll rtCtrl = rtCtrl + roll if mc.objExists(lfCtrl) and mc.objExists(rtCtrl): swapAnim(lfCtrl, rtCtrl) mc.scaleKey(lfCtrl, at=['tx', 'ty', 'tz'], valueScale=-1.0, valuePivot=0.0) mc.scaleKey(rtCtrl, at=['tx', 'ty', 'tz'], valueScale=-1.0, valuePivot=0.0) # Fingers for ctrl in finger: # Get Left/Right Nodes lfCtrl = ctrl.replace('SIDE', left) rtCtrl = ctrl.replace('SIDE', right) ind = 1 while mc.objExists(lfCtrl + str(ind)) and mc.objExists(rtCtrl + str(ind)): lfCtrlInd = lfCtrl + str(ind) rtCtrlInd = rtCtrl + str(ind) swapAnim(lfCtrlInd, rtCtrlInd) mc.scaleKey(lfCtrlInd, at=['tx', 'ty', 'tz'], valueScale=-1.0, valuePivot=0.0) mc.scaleKey(rtCtrlInd, at=['tx', 'ty', 'tz'], valueScale=-1.0, valuePivot=0.0) if not ind: ind = 0 ind += 1 # Legs for ctrl in [upLeg, leg, foot, toe]: # Get Left/Right Nodes lfCtrl = ctrl.replace('SIDE', left) rtCtrl = ctrl.replace('SIDE', right) if mc.objExists(lfCtrl) and mc.objExists(rtCtrl): swapAnim(lfCtrl, rtCtrl) mc.scaleKey(lfCtrl, at=['tx', 'ty', 'tz'], valueScale=-1.0, valuePivot=0.0) mc.scaleKey(rtCtrl, at=['tx', 'ty', 'tz'], valueScale=-1.0, valuePivot=0.0) # Get Roll Nodes lfCtrl = lfCtrl + roll rtCtrl = rtCtrl + roll if mc.objExists(lfCtrl) and mc.objExists(rtCtrl): swapAnim(lfCtrl, rtCtrl) mc.scaleKey(lfCtrl, at=['tx', 'ty', 'tz'], valueScale=-1.0, valuePivot=0.0) mc.scaleKey(rtCtrl, at=['tx', 'ty', 'tz'], valueScale=-1.0, valuePivot=0.0)
def AnimExport(): if cmds.objExists('imagePlane1'): cmds.hide('imagePlane1') cmds.hide('*_LOC') # делаю несколько проверок # создан ли character set if cmds.objExists('default_character'): if cmds.objExists('*Source'): activeClipCheck = cmds.clip('default_character', active = True, q = True) if activeClipCheck != 'default': cmds.select(animName + 'Source') cmds.select(GetInfo.charSet + 'Clips1', add = True) cmds.select(GetInfo.animCurvesList, add = True) # делаю экспорт clip в .ma cmds.file(GetInfo.clipPath + GetInfo.animName + '.ma', type='mayaAscii', exportSelected=True) # делаю экспорт анимации в .atom maxTime = cmds.playbackOptions( q = True, maxTime = True) cmds.select(ctrlsList) mel.eval('string $animName = `python "animName"`;') mel.eval('string $maxTime = `python "maxTime"`;') mel.eval('loadPlugin atomImportExport') mel.eval('file -force -options "precision=8;statics=1;baked=0;sdk=0;constraint=0;animLayers=1;selected=selectedOnly;whichRange=1;range=1:$maxTime;hierarchy=none;controlPoints=1;useChannelBox=1;options=keys;copyKeyCmd=-animation objects -option keys -hierarchy none -controlPoints 1 " -typ "atomExport" -es ("z:/.src/shared/chr/_face/.anims_atom/" + $animName + ".atom");') # сжимаю анимацию в два раза, чтобы она соответствовала реальному времени cmds.select(ctrlsList) cmds.scaleKey(iub = False, ts = 0.5, tp = 1, fs = 0.5, fp = 1, vs = 1, vp = 0) # задаю новые границы timeline maxTime = (cmds.playbackOptions( q = True, maxTime = True)/2) maxTime = round(maxTime) cmds.playbackOptions(maxTime = int(maxTime)) # делаю экспорт видео для просмотра cmds.playblast(fo = True, v= False, fmt = 'movie', f = 'z:/.src/shared/chr/_face/.anims_preview_database/' + animName + '.avi' ) # делаю проверку на объекты, которые не подходят к названию # нужна только для старых анимаций, созданых раньше июля 2015 if cmds.objExists('eyes_CTRL'): cmds.rename('eyes_CTRL', 'eyes_ctrl') # Удаляю группу и локаторы костей языка # Временно, пока не настроил их if cmds.objExists('tongue_1_GRP'): cmds.delete('tongue_1_GRP', 'tongue_2_GRP') # создаю переменные, где храню значение начала и конца timeline currEndTime = cmds.playbackOptions( q=True, maxTime=True ) currStartTime = cmds.playbackOptions( q=True, minTime=True ) # выделяю все лицевые контроллеры cmds.select(ctrlsList) cmds.currentTime(currStartTime, edit=True) cmds.setKeyframe(ctrlsList) cmds.currentTime(currEndTime, edit=True) cmds.setKeyframe(ctrlsList) # смещаю ключи на 10 кадров вперед относительно их позиции cmds.keyframe(edit=True, relative = True, timeChange = (0 + 10)) # задаю новые границы timeline currEndTime += 20 cmds.playbackOptions( minTime=0, maxTime=currEndTime ) # создаю функцию, которая обнуляю все каналы объектов из списка def SetKeysToZero(): global ctrlsList for ctrl in ctrlsList: attrs = cmds.listAttr(ctrl, k=True) #создает список атрибутов для каждого из выделенных объектов for attr in attrs: #для каждого атрибута из списка атрибутов if attr != "visibility": #если он не называется cmds.setAttr(ctrl + "." + attr, 0) #имя объекта+точка+название атрибута равняется нулю # ставлю нулевые ключи лицевых контроллеров вначале и конце timeline cmds.currentTime(currStartTime, edit=True) SetKeysToZero() cmds.currentTime(currEndTime, edit=True) SetKeysToZero() # запекаю анимации на timeline для всех костей fullSkeletonList = cmds.ls(type = 'joint') cmds.select(fullSkeletonList) cmds.bakeResults(fullSkeletonList, t=(currStartTime,currEndTime), simulation=True, sb=1) # перевожу переменные pytjon в mel mel.eval('string $animName = `python "animName"`;') mel.eval('string $animFBXPath = `python "animFBXPath"`;') # делаю экспорт выделенных костей в .fbx с именем файла fullSkeletonList = cmds.ls(type = 'joint') cmds.select(fullSkeletonList) mel.eval('FBXExportConstraints -v 0') mel.eval('FBXLoadExportPresetFile -f "c:/Users/user/Documents/maya/FBX/Presets/2014.1/export/AnimationOnly.fbxexportpreset"') mel.eval('FBXExport -f ($animFBXPath + $animName + ".fbx") -s') # создаю лог работы print '\n---------- export log:----------\n' if os.path.exists(atomPath + animName + '.atom'): print '.atom exported' else: print '.atom NOT exported' if os.path.exists(clipPath + animName + '.ma'): print '.ma exported' else: print '.ma NOT exported' if os.path.exists(animPreviewPath + animName + '.avi'): print '.avi exported' else: print '.avi NOT exported' if os.path.exists(animFBXPath + animName + '.fbx'): print '.fbx exported' else: print '.fbx NOT exported'
def setValues(self, animCurves): cmds.refresh(suspend=True) cmds.undoInfo(openChunk=True) cmds.undoInfo(closeChunk=True) cmds.undoInfo(openChunk=True) cmds.undoInfo(closeChunk=True) cmds.undoInfo(openChunk=True) cmds.undoInfo(closeChunk=True) cmds.undoInfo(openChunk=True) self.removeMessages() self.warn() values = self.getCurrentValues(animCurves) newKeyValues = values["keyValues"] timeValues = values["timeValues"] offsetValues = [] offsetPercentsA = [] offsetPercentsB = [] pivotAs = [] pivotBs = [] self.animCurvesToSend = [] for n, loopCurve in enumerate(animCurves): oldVal = self.currentValues[loopCurve][0] newVal = newKeyValues[n][0] if self.blendRangeMode: pivotA = cmds.keyframe( loopCurve, query=True, eval=True, time=(self.range[0], self.range[0]), valueChange=True )[0] pivotB = cmds.keyframe( loopCurve, query=True, eval=True, time=(self.range[1], self.range[1]), valueChange=True )[0] if oldVal == pivotA: pivotA = newVal offsetPercentA = 0 else: offsetPercentA = float((newVal - pivotA) / (oldVal - pivotA)) if oldVal == pivotB: pivotB = newVal offsetPercentB = 0 else: offsetPercentB = float((newVal - pivotB) / (oldVal - pivotB)) offsetPercentsA.append(offsetPercentA) offsetPercentsB.append(offsetPercentB) pivotAs.append(pivotA) pivotBs.append(pivotB) else: offsetVal = newVal - oldVal offsetValues.append(offsetVal) # reset change cmds.undoInfo(stateWithoutFlush=False) for loopCurve in self.allValues.keys(): if loopCurve in animCurves: valueChange = self.allValues[loopCurve] for n, loopValue in enumerate(valueChange): cmds.keyframe(loopCurve, edit=True, index=(n, n), valueChange=loopValue) # self.allValues[] = {} cmds.undoInfo(stateWithoutFlush=True) # set values for all keys curvesToUpdate = [] if self.blendRangeMode: for n, loopCurve in enumerate(animCurves): time = timeValues[n] timeOffsetA = 0.01 timeOffsetB = 0.01 if time[0] == self.range[0]: timeOffsetA = 0 if time[1] == self.range[1]: timeOffsetB = 0 if timeOffsetA != 0 and timeOffsetB != 0 and not self.range[0] < time[0] <= time[1] < self.range[1]: cmds.warning("Selected keys out of range %s" % self.range) continue offsetPercentA = offsetPercentsA[n] offsetPercentB = offsetPercentsB[n] # if offsetPercentA != 0 or offsetPercentB != 0: pivotA = pivotAs[n] pivotB = pivotBs[n] curvesToUpdate.append(loopCurve) cmds.scaleKey( loopCurve, time=(self.range[0] + timeOffsetA, time[1]), valuePivot=pivotA, valueScale=offsetPercentA ) cmds.scaleKey( loopCurve, time=(time[1] + 0.01, self.range[1] - timeOffsetB), valuePivot=pivotB, valueScale=offsetPercentB, ) else: for n, loopCurve in enumerate(animCurves): if offsetValues[n] != 0: curvesToUpdate.append(loopCurve) if self.range == "All Keys": # pass cmds.keyframe(loopCurve, edit=True, valueChange=offsetValues[n], relative=True) else: cmds.keyframe( loopCurve, edit=True, time=(self.range[0], self.range[1]), valueChange=offsetValues[n], relative=True, ) self.updateCurrentValues(curvesToUpdate) cmds.undoInfo(closeChunk=True) cmds.refresh(suspend=False)
def curve(anim_curve, time_filter, skip_cycle=True, trim=False): if not cmds.objExists(anim_curve): print "Could not find {0}".format(anim_curve) if cmds.nodeType(anim_curve) not in ( "animCurveTL", "animCurveTA", "animCurveTT", "animCurveTU", ): print 'Skipping non-time-based curve {0}'.format(anim_curve) return anim_curve # If a trim hasn't been specified then treat simple retimes as # global offsets or scales. if not trim: # If the time filter is a single value pair we calculate the # offset and apply it to the entire framerange and return the # anim_curve. if len(time_filter) == 1: offset = time_filter[0][0] - time_filter[0][1] src_keys = cmds.keyframe(anim_curve, query=True) new_start = min(src_keys) + offset new_end = max(src_keys) + offset cmds.scaleKey( anim_curve, time=(min(src_keys), max(src_keys)), newStartTime=new_start, newEndTime=new_end, ) return anim_curve # If there are only two values then it is a simple scale. # Calculate the scale and apply it to the entire key range. If # it is a held frame then treat it as a complex retime. if len(time_filter) == 2: new_start, src_start = time_filter[0] new_end, src_end = time_filter[1] if src_start != src_end: scale = (float(new_end) - new_start) / (src_end - src_start) offset = new_start - (src_start * scale) src_keys = cmds.keyframe(anim_curve, query=True) if not src_keys: cmds.select(anim_curve) new_start = min(src_keys) * scale + offset new_end = max(src_keys) * scale + offset cmds.scaleKey( anim_curve, time=(min(src_keys), max(src_keys)), newStartTime=new_start, newEndTime=new_end, ) return anim_curve # If the curve has a cycle on it then a complex retime will be # unpredictable. So if the skip_cycle value is true we just return # the curve unchanged. pre_inf = cmds.getAttr("{0}.preInfinity".format(anim_curve)) post_inf = cmds.getAttr("{0}.postInfinity".format(anim_curve)) if pre_inf > 2 or post_inf > 2: print 'No retime applied to cycling curve {0}'.format(anim_curve) return anim_curve # Convert the remap frame pairs (old frame/new frame) into time # blocks (old start, old end, new start, new end) so we can manage # regions instead of points. time_blocks = [] floor_frame = "Initialised." for x in range(len(time_filter) - 1): # Unpack the current and next time values. new_start, src_start = time_filter[x] new_end, src_end = time_filter[x + 1] time_blocks.append(( src_start, src_end, new_start, new_end, )) # Ensure the time blocks don't overlap. if floor_frame == "Initialised.": floor_frame = new_start if new_end <= floor_frame: cmds.error("Time filter overlaps: {0}".format(time_filter)) else: floor_frame = new_end # Add a keyframe at each remap point, if one does not already exist, # and unlock the tangents so they can be remapped independently. for frame, new_frame in time_filter: if not cmds.keyframe(anim_curve, time=(new_frame, ), query=True): cmds.setKeyframe(anim_curve, insert=True, time=(new_frame, )) cmds.keyTangent(anim_curve, edit=True, time=(frame, ), lock=False) # Create a temporary curve to transcribe the remap data to and a # buffer curve to hold the keys from each time block while we scale # them. node_type = cmds.nodeType(anim_curve) temp_curve = cmds.createNode(node_type, name=anim_curve + 'remap_temp', skipSelect=True) # Transcribe the remapped keys onto the temporary curve using the # data in the time_blocks list. for time_block in time_blocks: src_start, src_end, new_start, new_end = time_block # If the time block uses the same source frame for the whole # time block then we need to treat it as a held frame. if src_end == src_start: # Add a duplicate key at the start and end of the time block. keys = cmds.keyframe(anim_curve, time=(src_start, ), query=True) key_data = crv.key_info_by_time(anim_curve, keys[0]) key_data['key_time'] = new_end crv.add_keyframe(temp_curve, key_data) key_data['key_time'] = new_start key_data['out_type'] = 'step' key_data['out_angle'] = 0 key_data['out_weight'] = 0 crv.add_keyframe(temp_curve, key_data) # If the time block uses different source frames at the start # and end of the time block then we need to scale the region # between those frames. else: # If we're scaling backwards then shuffle the values # to work with the scaleKey script if src_start > src_end: (src_start, src_end) = (src_end, src_start) (new_start, new_end) = (new_end, new_start) reverse = True else: reverse = False # Copy those key in the time block to a buffer curve. buffer_curve = cmds.createNode(node_type, name=anim_curve + 'buffer_temp', skipSelect=True) keys = cmds.keyframe(anim_curve, time=( src_start, src_end, ), query=True) for key in keys: key_data = crv.key_info_by_time(anim_curve, key) crv.add_keyframe(buffer_curve, key_data) # Scale the keys on the buffer curve. cmds.scaleKey( buffer_curve, time=(src_start, src_end), newStartTime=new_start, newEndTime=new_end, ) # Stepped keys break if they're reversed, so this is a fix # for that. if reverse: for key_index in range(0, len(keys) - 1): if cmds.keyTangent(anim_curve, outTangentType=True, index=(key_index, key_index), query=True)[0] == 'step': new_index = len(keys) - key_index - 2 cmds.keyTangent(buffer_curve, index=(new_index, ), outTangentType='stepnext') if cmds.keyTangent(anim_curve, outTangentType=True, index=(key_index, key_index), query=True)[0] == 'stepnext': new_index = len(keys) - key_index - 2 cmds.keyTangent(buffer_curve, index=(new_index, ), outTangentType='step') # Transcribe the keys to the temp curve. buffer_keys = cmds.keyframe(buffer_curve, query=True) temp_keys = cmds.keyframe(temp_curve, query=True) for key_index in range(0, len(buffer_keys)): key_data = crv.key_info_by_index(buffer_curve, key_index) # If the start/end keys already exist on the curve we # don't want to overwrite the tangents before or after # the time block. if temp_keys and key_index == 0: if key_data['key_time'] in temp_keys: old_data = crv.key_info_by_time( temp_curve, key_data['key_time']) key_data['in_type'] = old_data['in_type'] key_data['in_angle'] = old_data['in_angle'] key_data['in_weight'] = old_data['in_weight'] if temp_keys and key_index == len(buffer_keys) - 1: if key_data['key_time'] in temp_keys: old_data = crv.key_info_by_time( temp_curve, key_data['key_time']) key_data['out_type'] = old_data['out_type'] key_data['out_angle'] = old_data['out_angle'] key_data['out_weight'] = old_data['out_weight'] crv.add_keyframe(temp_curve, key_data) cmds.delete(buffer_curve) # Transfer the keys from the temp curve to the original curve. src_keys = cmds.keyframe(anim_curve, query=True) temp_keys = cmds.keyframe(temp_curve, query=True) # Add a placeholder keyframe below the range of either curve. (If # we delete all the keyframes on a curve it will delete the curve # node as well.) min_key = min(src_keys) - min(temp_keys) - 1 cmds.setKeyframe( anim_curve, time=min_key, value=0, inTangentType='linear', outTangentType='linear', ) # Delete all other keys on the source curve. cmds.cutKey(anim_curve, time=(min(src_keys), max(src_keys)), option='keys') # Copy the keys from the temp curve. for key in temp_keys: key_data = crv.key_info_by_time(temp_curve, key) crv.add_keyframe(anim_curve, key_data) cmds.delete(temp_curve) # Delete the placeholder key. cmds.cutKey(anim_curve, time=(min_key, ), option='keys') return anim_curve
def scale_times(self, scale, pivot): cmds.scaleKey(self.path, timeScale=scale, timePivot=pivot)
def shrink(): lastValue = mc.keyframe(q=1, lastSelected=1, vc=1) mc.scaleKey(vs=0.9, vp=lastValue[0])
def setValues(self, animCurves): cmds.refresh(suspend=True) cmds.undoInfo(openChunk=True) cmds.undoInfo(closeChunk=True) cmds.undoInfo(openChunk=True) cmds.undoInfo(closeChunk=True) cmds.undoInfo(openChunk=True) cmds.undoInfo(closeChunk=True) cmds.undoInfo(openChunk=True) self.removeMessages() self.warn() values = self.getCurrentValues(animCurves) newKeyValues = values["keyValues"] timeValues = values["timeValues"] offsetValues = [] offsetPercentsA = [] offsetPercentsB = [] pivotAs = [] pivotBs = [] self.animCurvesToSend = [] for n, loopCurve in enumerate(animCurves): oldVal = self.currentValues[loopCurve][0] newVal = newKeyValues[n][0] if self.blendRangeMode: pivotA = cmds.keyframe(loopCurve, query=True, eval=True, time=(self.range[0],self.range[0]), valueChange=True)[0] pivotB = cmds.keyframe(loopCurve, query=True, eval=True, time=(self.range[1],self.range[1]), valueChange=True)[0] if oldVal == pivotA: pivotA = newVal offsetPercentA = 0 else: offsetPercentA = float((newVal-pivotA)/(oldVal-pivotA)) if oldVal == pivotB: pivotB = newVal offsetPercentB = 0 else: offsetPercentB = float((newVal-pivotB)/(oldVal-pivotB)) offsetPercentsA.append(offsetPercentA) offsetPercentsB.append(offsetPercentB) pivotAs.append(pivotA) pivotBs.append(pivotB) else: offsetVal = newVal - oldVal offsetValues.append(offsetVal) #reset change cmds.undoInfo(stateWithoutFlush=False) for loopCurve in self.allValues.keys(): if loopCurve in animCurves: valueChange = self.allValues[loopCurve] for n, loopValue in enumerate(valueChange): cmds.keyframe(loopCurve, edit=True, index=(n,n), valueChange=loopValue) #self.allValues[] = {} cmds.undoInfo(stateWithoutFlush=True) #set values for all keys curvesToUpdate = [] if self.blendRangeMode: for n, loopCurve in enumerate(animCurves): time = timeValues[n] timeOffsetA = .01 timeOffsetB = .01 if time[0] == self.range[0]: timeOffsetA = 0 if time[1] == self.range[1]: timeOffsetB = 0 if timeOffsetA != 0 and timeOffsetB != 0 and not self.range[0] < time[0] <= time[1] < self.range[1]: cmds.warning("Selected keys out of range %s"%self.range) continue offsetPercentA = offsetPercentsA[n] offsetPercentB = offsetPercentsB[n] #if offsetPercentA != 0 or offsetPercentB != 0: pivotA = pivotAs[n] pivotB = pivotBs[n] curvesToUpdate.append(loopCurve) cmds.scaleKey(loopCurve, time=(self.range[0]+timeOffsetA, time[1]), valuePivot=pivotA, valueScale=offsetPercentA) cmds.scaleKey(loopCurve, time=(time[1]+.01, self.range[1]-timeOffsetB), valuePivot=pivotB, valueScale=offsetPercentB) else: for n, loopCurve in enumerate(animCurves): if offsetValues[n] != 0: curvesToUpdate.append(loopCurve) if self.range == "All Keys": #pass cmds.keyframe(loopCurve, edit=True, valueChange=offsetValues[n], relative=True) else: cmds.keyframe(loopCurve, edit=True, time=(self.range[0], self.range[1]), valueChange=offsetValues[n], relative=True) self.updateCurrentValues(curvesToUpdate) cmds.undoInfo(closeChunk=True) cmds.refresh(suspend=False)
def flip(): lastValue = mc.keyframe(q=1, lastSelected=1, vc=1) mc.scaleKey(vs=-1, vp=lastValue[0])
def mirrorAnimation(): mirrorPose() l = mc.ls(sl=True, o=True) or [] for n in l: if not n.endswith("_ctrl"): continue side = "_lf" side2 = "_rt" if "_rt" in n: side = "_rt" side2 = "_lf" n2 = n.replace(side, side2) if not mc.objExists(n2): continue # delete existing anim curves attached to the node on the "other" side l2 = mc.listAttr(n2, k=True) or [] for a in l2: l3 = mc.listConnections( n2 + "." + a, s=True, d=False, scn=True, t="animCurve") or [] for n3 in l3: try: mc.delete(n3) except: pass # copy existing anim curves from the node on "this" onto the node on the "other" side l2 = mc.listAttr(n, k=True, sn=True) or [] for a in l2: try: n3 = mc.listConnections(n + "." + a, s=True, d=False, scn=True, t="animCurve")[0] except: continue n3 = mc.duplicate(n3)[0] try: mc.connectAttr(n3 + ".output", n2 + "." + a) except: mc.delete(n3) continue # mirror keyframes if needed if "_ik_" in n and a in ["tx", "ry", "rz"]: if "shoulder_" in n and a in ["ry", "rz"]: continue mc.select(n3) mc.selectKey(n3, k=True, t=(-999999999, 999999999)) mc.scaleKey(iub=False, ts=1, tp=0, fs=1, fp=0, vs=-1, vp=0, an="keys") elif "_fk" in n and "head_eye_" in n and a == "ry": mc.select(n3) mc.selectKey(n3, k=True, t=(-999999999, 999999999)) mc.scaleKey(iub=False, ts=1, tp=0, fs=1, fp=0, vs=-1, vp=0, an="keys") elif n.plit(":")[-1].startswith("finger_") and a in [ "ty", "rx", "rz" ]: mc.select(n3) mc.selectKey(n3, k=True, t=(-999999999, 999999999)) mc.scaleKey(iub=False, ts=1, tp=0, fs=1, fp=0, vs=-1, vp=0, an="keys") elif "_pv_" in n and a in ["tx", "ty", "tz"]: mc.select(n3) mc.selectKey(n3, k=True, t=(-999999999, 999999999)) mc.scaleKey(iub=False, ts=1, tp=0, fs=1, fp=0, vs=-1, vp=0, an="keys") if len(l) > 0: mc.select(l)
def retime_animation_curves(animation_curves, start_frame, end_frame, new_start_frame, new_end_frame, add_boundary_keyframes=False, offset_contiguous_animation=True, snap_keys=True): """ Scale time range but also offset what's contiguous to keep continuity. :param list[str] animation_curves: animation curves names :param float start_frame: :param float end_frame: :param float new_start_frame: :param float new_end_frame: :param bool add_boundary_keyframes: add keyframes before and after retime to ensure de animation will not change out of the scaled range. :param bool offset_contiguous_animation: shift the animation before and after the scale to match the new timing. :param bool snap_key: round the new key frame time to the closest int. """ # Define offsets happening before and after: end_offset = new_end_frame - end_frame start_offset = new_start_frame - start_frame # Define offset functions: keys = cmds.keyframe(animation_curves, query=True) max_keyframe = max(keys) + start_offset + end_offset offset_after_function = partial(cmds.keyframe, animation_curves, edit=True, t=(end_frame + 1, max_keyframe), relative=True, timeChange=end_offset, option='over') min_keyframe = min(keys) - end_offset - start_offset offset_before_function = partial(cmds.keyframe, animation_curves, edit=True, t=(min_keyframe, start_frame - 1), relative=True, timeChange=start_offset, option='over') if add_boundary_keyframes: cmds.setKeyframe(animation_curves, time=start_frame, inTangentType="linear", outTangentType="linear") cmds.setKeyframe(animation_curves, time=end_frame, inTangentType="linear", outTangentType="linear") # Offsets in case of expansion: if offset_contiguous_animation and end_offset > 0: offset_after_function() if offset_contiguous_animation and start_offset < 0: offset_before_function() # Retime/scale animation: cmds.scaleKey(animation_curves, time=(start_frame, end_frame), newStartTime=new_start_frame, newEndTime=new_end_frame) if snap_keys: cmds.snapKey(animation_curves, t=(new_start_frame, new_end_frame)) # Offsets in case of shrinking: if offset_contiguous_animation and end_offset < 0: offset_after_function() if offset_contiguous_animation and start_offset > 0: offset_before_function()