def addMarksToScene(marks): ''' This is temp and will possibly be rolled into future releases. ''' start, end = utl.frameRange() camera = utl.getCurrentCamera() camShape = mc.listRelatives(camera, shapes=True)[0] aov = mc.getAttr(camShape + '.horizontalFilmAperture') name = 'ml_stopwatch_' numStopwatches = len(mc.ls(name + '*', type='locator')) top = mc.spaceLocator(name=name + '#') ename = ':'.join([str(x) for x in marks]) mc.addAttr(top, longName='keyTimes', at='enum', enumName=ename, keyable=True) markRange = float(marks[-1] - marks[0]) viewWidth = aov * 2 viewHeight = -0.4 * aov + (numStopwatches * aov * 0.08) depth = 5 for mark in marks[1:-1]: ann = mc.annotate(top, text=str(mark)) mc.setAttr(ann + '.displayArrow', 0) #parent annT = mc.parent(mc.listRelatives(ann, parent=True, path=True), top)[0] annT = mc.rename(annT, 'mark_' + str(round(mark))) ann = mc.listRelatives(annT, shapes=True, path=True)[0] #set the position normalX = float(mark - marks[0]) / markRange - 0.5 mc.setAttr(annT + '.translateX', viewWidth * normalX * 2) mc.setAttr(annT + '.translateY', viewHeight) mc.setAttr(annT + '.translateZ', -depth) #keyframe for color mc.setAttr(ann + '.overrideEnabled', 1) mc.setKeyframe(ann, attribute='overrideColor', value=17, time=(int(marks[0] - 1), int(mark + 1))) mc.setKeyframe(ann, attribute='overrideColor', value=13, time=(int(mark), )) mc.keyTangent(ann + '.overrideColor', ott='step') mc.select(clear=True) mc.parentConstraint(camera, top)
def addMarksToScene(marks): ''' This is temp and will possibly be rolled into future releases. ''' start,end = utl.frameRange() camera = utl.getCurrentCamera() camShape = mc.listRelatives(camera, shapes=True)[0] aov = mc.getAttr(camShape+'.horizontalFilmAperture') name = 'ml_stopwatch_' numStopwatches = len(mc.ls(name+'*', type='locator')) top = mc.spaceLocator(name=name+'#') ename = ':'.join([str(x) for x in marks]) mc.addAttr(top, longName='keyTimes', at='enum', enumName=ename, keyable=True) markRange = float(marks[-1]-marks[0]) viewWidth = aov*2 viewHeight = -0.4*aov+(numStopwatches*aov*0.08) depth = 5 for mark in marks[1:-1]: ann = mc.annotate(top, text=str(mark)) mc.setAttr(ann+'.displayArrow', 0) #parent annT = mc.parent(mc.listRelatives(ann, parent=True, path=True), top)[0] annT = mc.rename(annT, 'mark_'+str(round(mark))) ann = mc.listRelatives(annT, shapes=True, path=True)[0] #set the position normalX = float(mark-marks[0])/markRange-0.5 mc.setAttr(annT+'.translateX', viewWidth*normalX*2) mc.setAttr(annT+'.translateY', viewHeight) mc.setAttr(annT+'.translateZ', -depth) #keyframe for color mc.setAttr(ann+'.overrideEnabled', 1) mc.setKeyframe(ann, attribute='overrideColor', value=17, time=(int(marks[0]-1),int(mark+1))) mc.setKeyframe(ann, attribute='overrideColor', value=13, time=(int(mark),)) mc.keyTangent(ann+'.overrideColor', ott='step') mc.select(clear=True) mc.parentConstraint(camera, top)
def _startButton(*args): ''' Run when the start button is pressed, gathers args and starts the stopwatch. ''' global STOPWATCH _setButtonMark() rounded = mc.checkBoxGrp('ml_stopwatch_round_checkBox', query=True, value1=True) kwargs = dict() kwargs['startFrame'], null = utl.frameRange() if rounded: kwargs['roundTo'] = 0 STOPWATCH = Stopwatch(**kwargs) STOPWATCH.start()
def cutUnselected(selectionOption=1, setKey=True): keySel = _getKeySelection(selectionOption) start = None end = None if keySel.keyRange(): start, end = keySel.time else: start, end = utl.frameRange() if setKey: if keySel.findKeyframe('previous', time=(start, )) < start: mc.setKeyframe(keySel.curves, time=(start, ), insert=True) if keySel.findKeyframe('next', time=(end - 1, )) > end - 1: mc.setKeyframe(keySel.curves, time=(end - 1, ), insert=True) keySel.cutKey(time=(':' + str(start), )) keySel.cutKey(time=(str(end) + ':', ))
def cutUnselected(selectionOption=1, setKey=True): keySel = _getKeySelection(selectionOption) start = None end = None if keySel.keyRange(): start, end = keySel.time else: start, end = utl.frameRange() if setKey: if keySel.findKeyframe('previous', time=(start,)) < start: mc.setKeyframe(keySel.curves, time=(start,), insert=True) if keySel.findKeyframe('next', time=(end-1,)) > end-1: mc.setKeyframe(keySel.curves, time=(end-1,), insert=True) keySel.cutKey(time=(':'+str(start),)) keySel.cutKey(time=(str(end)+':',))
def bakeCenterOfMass(*args): ''' Bake root animation to center of mass. ''' sel = mc.ls(sl=True) if not len(sel) == 1: raise RuntimeError('Please select the root control of your puppet.') root, com = getRootAndCOM(sel[0]) if not root: root = sel[0] if not com: com = createCenterOfMass() start, end = utl.frameRange() with utl.IsolateViews(): mc.bakeResults(com, time=(start,end), sampleBy=1, attribute=['tx','ty','tz'], simulation=True) rootOffset = mc.group(em=True, name='rootOffset') rootOffset = mc.parent(rootOffset, com)[0] #bake utl.matchBake(source=[root], destination=[rootOffset], bakeOnOnes=True, maintainOffset=False, preserveTangentWeight=False, translate=True, rotate=True) mc.cutKey(root, attribute=['tx','ty','tz','rx','ry','rz']) mc.parentConstraint(rootOffset, root) mc.select(com)
def traceArc(space='camera'): ''' The main function for creating the arc. ''' if space != 'world' and space != 'camera': OpenMaya.MGlobal.displayWarning('Improper space argument.') return global ML_TRACE_ARC_PREVIOUS_SELECTION global ML_TRACE_ARC_PREVIOUS_SPACE #save for reset: origTime = mc.currentTime(query=True) #frame range frameRange = utl.frameRange() start = frameRange[0] end = frameRange[1] #get neccesary nodes objs = mc.ls(sl=True, type='transform') if not objs: OpenMaya.MGlobal.displayWarning('Select objects to trace') return ML_TRACE_ARC_PREVIOUS_SELECTION = objs ML_TRACE_ARC_PREVIOUS_SPACE = space cam = None nearClipPlane = None shortCam = '' if space=='camera': cam = utl.getCurrentCamera() #the arc will be placed just past the clip plane distance, but no closer than 1 unit. nearClipPlane = max(mc.getAttr(cam+'.nearClipPlane'),1) shortCam = mc.ls(cam, shortNames=True)[0] topGroup = 'ml_arcGroup' worldGrp = 'ml_arcWorldGrp' localGrp = 'ml_localGrp_'+shortCam #create nodes if not mc.objExists(topGroup): topGroup = mc.group(empty=True, name=topGroup) parentGrp = topGroup if space=='world' and not mc.objExists(worldGrp): worldGrp = mc.group(empty=True, name=worldGrp) mc.setAttr(worldGrp+'.overrideEnabled',1) mc.setAttr(worldGrp+'.overrideDisplayType',2) mc.parent(worldGrp, topGroup) parentGrp = mc.ls(worldGrp)[0] if space == 'camera': camConnections = mc.listConnections(cam+'.message', plugs=True, source=False, destination=True) if camConnections: for cc in camConnections: if '.ml_parentCam' in cc: localGrp = mc.ls(cc, o=True)[0] if not mc.objExists(localGrp): localGrp = mc.group(empty=True, name=localGrp) mc.parentConstraint(cam, localGrp) mc.setAttr(localGrp+'.overrideEnabled',1) mc.setAttr(localGrp+'.overrideDisplayType',2) mc.parent(localGrp, topGroup) mc.addAttr(localGrp, at='message', longName='ml_parentCam') mc.connectAttr(cam+'.message', localGrp+'.ml_parentCam') parentGrp = mc.ls(localGrp)[0] #group per object: group = list() points = list() for i,obj in enumerate(objs): sn = mc.ls(obj,shortNames=True)[0] name = sn.replace(':','_') points.append(list()) groupName = 'ml_%s_arcGrp' % name if mc.objExists(groupName): mc.delete(groupName) group.append(mc.group(empty=True, name=groupName)) group[i] = mc.parent(group[i],parentGrp)[0] mc.setAttr(group[i]+'.translate', 0,0,0) mc.setAttr(group[i]+'.rotate', 0,0,0) with utl.UndoChunk(): with utl.IsolateViews(): #helper locator loc = mc.spaceLocator()[0] mc.parent(loc,parentGrp) #frame loop: time = range(int(start),int(end+1)) for t in time: mc.currentTime(t, edit=True) #object loop for i,obj in enumerate(objs): objPnt = mc.xform(obj, query=True, worldSpace=True, rotatePivot=True) if space=='camera': camPnt = mc.xform(cam, query=True, worldSpace=True, rotatePivot=True) objVec = euclid.Vector3(objPnt[0],objPnt[1],objPnt[2]) camVec = euclid.Vector3(camPnt[0],camPnt[1],camPnt[2]) vec = objVec-camVec vec.normalize() #multiply here to offset from camera vec=vec*nearClipPlane*1.2 vec+=camVec mc.xform(loc, worldSpace=True, translation=vec[:]) trans = mc.getAttr(loc+'.translate') points[i].append(trans[0]) elif space=='world': points[i].append(objPnt) mc.delete(loc) #create the curves and do paint effects mc.ResetTemplateBrush() brush = mc.getDefaultBrush() mc.setAttr(brush+'.screenspaceWidth',1) mc.setAttr(brush+'.distanceScaling',0) mc.setAttr(brush+'.brushWidth',0.005) for i,obj in enumerate(objs): #setup brush for path mc.setAttr(brush+'.screenspaceWidth',1) mc.setAttr(brush+'.distanceScaling',0) mc.setAttr(brush+'.brushWidth',0.003) #color for c in ('R','G','B'): color = random.uniform(0.3,0.7) mc.setAttr(brush+'.color1'+c,color) baseCurve = mc.curve(d=3,p=points[i]) #fitBspline makes a curve that goes THROUGH the points, a more accurate path curve = mc.fitBspline(baseCurve, constructionHistory=False, tolerance=0.001) mc.delete(baseCurve) #paint fx mc.AttachBrushToCurves(curve) stroke = mc.ls(sl=True)[0] stroke = mc.parent(stroke,group[i])[0] mc.setAttr(stroke+'.overrideEnabled',1) mc.setAttr(stroke+'.overrideDisplayType',2) mc.setAttr(stroke+'.displayPercent',92) mc.setAttr(stroke+'.sampleDensity',0.5) mc.setAttr(stroke+'.inheritsTransform',0) mc.setAttr(stroke+'.translate',0,0,0) mc.setAttr(stroke+'.rotate',0,0,0) curve = mc.parent(curve,group[i])[0] mc.setAttr(curve+'.translate',0,0,0) mc.setAttr(curve+'.rotate',0,0,0) mc.hide(curve) #setup brush for tics if space=='camera': mc.setAttr(brush+'.brushWidth',0.008) if space=='world': mc.setAttr(brush+'.brushWidth',0.005) mc.setAttr(brush+'.color1G',0) mc.setAttr(brush+'.color1B',0) for t in range(len(points[i])): frameCurve = None if space=='camera': vec = euclid.Vector3(points[i][t][0],points[i][t][1],points[i][t][2]) vec*=0.98 frameCurve = mc.curve(d=1,p=[points[i][t],vec[:]]) elif space=='world': frameCurve = mc.circle(constructionHistory=False, radius=0.0001, sections=4)[0] mc.setAttr(frameCurve+'.translate', points[i][t][0], points[i][t][1] ,points[i][t][2]) constraint = mc.tangentConstraint(curve, frameCurve, aimVector=(0,0,1), worldUpType='scene') #mc.delete(constraint) #check for keyframe colorAttribute='color1G' if mc.keyframe(obj, time=((t+start-0.5),(t+start+0.5)), query=True): mc.setAttr(brush+'.color1R',1) else: mc.setAttr(brush+'.color1R',0) mc.AttachBrushToCurves(curve) stroke = mc.ls(sl=True)[0] thisBrush = mc.listConnections(stroke+'.brush', destination=False)[0] #setup keyframes for frame highlighting mc.setKeyframe(thisBrush, attribute='color1G', value=0, time=(start+t-1, start+t+1)) mc.setKeyframe(thisBrush, attribute='color1G', value=1, time=(start+t,)) stroke = mc.parent(stroke,group[i])[0] mc.hide(frameCurve) mc.setAttr(stroke+'.displayPercent',92) mc.setAttr(stroke+'.sampleDensity',0.5) frameCurve = mc.parent(frameCurve,group[i])[0] if space=='camera': mc.setAttr(stroke+'.inheritsTransform',0) mc.setAttr(stroke+'.pressureScale[1].pressureScale_Position', 1) mc.setAttr(stroke+'.pressureScale[1].pressureScale_FloatValue', 0) mc.setAttr(stroke+'.translate',0,0,0) mc.setAttr(stroke+'.rotate',0,0,0) mc.setAttr(frameCurve+'.translate',0,0,0) mc.setAttr(frameCurve+'.rotate',0,0,0) mc.currentTime(origTime, edit=True) panel = mc.getPanel(withFocus=True) mc.modelEditor(panel, edit=True, strokes=True) mc.select(objs,replace=True)
def matchBake(source=None, destination=None, bakeOnOnes=False, maintainOffset=False): if not source and not destination: sel = mc.ls(sl=True) if len(sel) != 2: OpenMaya.MGlobal.displayWarning('Select exactly 2 objects') return source = [sel[0]] destination = [sel[1]] #save for reset: resetTime = mc.currentTime(query=True) #frame range start, end = utl.frameRange() attributes = [ 'translateX', 'translateY', 'translateZ', 'rotateX', 'rotateY', 'rotateZ' ] duplicates = dict() keytimes = dict() constraint = list() itt = dict() ott = dict() #initialize allKeyTimes with start and end frames, since they may not be keyed allKeyTimes = [start, end] for s, d in zip(source, destination): #duplicate the destination dup = mc.duplicate(d, name='temp#', parentOnly=True)[0] for a in attributes: mc.setAttr(dup + '.' + a, lock=False, keyable=True) constraint.append( mc.parentConstraint(s, dup, maintainOffset=maintainOffset)) #cut keys on destination mc.cutKey(d, attribute=attributes, time=(start, end)) #set up our data dictionaries duplicates[d] = dup keytimes[d] = dict() itt[d] = dict() ott[d] = dict() #if we're baking on ones, we don't need keytimes if not bakeOnOnes: for a in attributes: currKeytimes = mc.keyframe(s, attribute=a, time=(start, end), query=True, timeChange=True) if not currKeytimes: continue keytimes[d][a] = currKeytimes allKeyTimes.extend(currKeytimes) itt[d][a] = mc.keyTangent(s, attribute=a, time=(start, end), query=True, inTangentType=True) ott[d][a] = mc.keyTangent(s, attribute=a, time=(start, end), query=True, outTangentType=True) #change fixed tangents to spline, because we can't set fixed tangents for i, each in enumerate(itt[d][a]): if each == 'fixed': itt[d][a][i] = 'spline' for i, each in enumerate(ott[d][a]): if each == 'fixed': ott[d][a][i] = 'spline' #in the future, save tangent in and out values #add the start and end frames and tangents if they're not keyed if not start in keytimes[d][a]: keytimes[d][a].insert(0, start) itt[d][a].insert(0, 'spline') ott[d][a].insert(0, 'spline') if not end in keytimes[d][a]: keytimes[d][a].append(end) itt[d][a].append('spline') ott[d][a].append('spline') #reverse these, because we want to pop but start from the beginning itt[d][a].reverse() ott[d][a].reverse() if bakeOnOnes: allKeyTimes = range(int(start), int(end) + 1) else: allKeyTimes = list(set(allKeyTimes)) allKeyTimes.sort() with utl.UndoChunk(): with utl.IsolateViews(): for frame in allKeyTimes: #cycle through all the frames mc.currentTime(frame, edit=True) for d in destination: for a in attributes: if bakeOnOnes: mc.setKeyframe(d, attribute=a, time=frame, value=mc.getAttr(duplicates[d] + '.' + a), itt='spline', ott='spline') elif a in keytimes[d] and frame in keytimes[d][a]: #tangent types line up with keytimes mc.setKeyframe(d, attribute=a, time=frame, value=mc.getAttr(duplicates[d] + '.' + a), itt=itt[d][a].pop(), ott=ott[d][a].pop()) #reset time and selection mc.currentTime(resetTime, edit=True) mc.select(destination, replace=True) mc.delete(duplicates.values()) mc.filterCurve(mc.listConnections(destination, type='animCurve')) if bakeOnOnes: mc.keyTangent(destination, attribute=attributes, itt='spline', ott='spline')
def matchBake(source=None, destination=None, bakeOnOnes=False, maintainOffset=False): if not source and not destination: sel = mc.ls(sl=True) if len(sel) != 2: OpenMaya.MGlobal.displayWarning("Select exactly 2 objects") return source = [sel[0]] destination = [sel[1]] # save for reset: resetTime = mc.currentTime(query=True) # frame range start, end = utl.frameRange() attributes = ["translateX", "translateY", "translateZ", "rotateX", "rotateY", "rotateZ"] duplicates = dict() keytimes = dict() constraint = list() itt = dict() ott = dict() # initialize allKeyTimes with start and end frames, since they may not be keyed allKeyTimes = [start, end] for s, d in zip(source, destination): # duplicate the destination dup = mc.duplicate(d, name="temp#", parentOnly=True)[0] for a in attributes: mc.setAttr(dup + "." + a, lock=False, keyable=True) constraint.append(mc.parentConstraint(s, dup, maintainOffset=maintainOffset)) # cut keys on destination mc.cutKey(d, attribute=attributes, time=(start, end)) # set up our data dictionaries duplicates[d] = dup keytimes[d] = dict() itt[d] = dict() ott[d] = dict() # if we're baking on ones, we don't need keytimes if not bakeOnOnes: for a in attributes: currKeytimes = mc.keyframe(s, attribute=a, time=(start, end), query=True, timeChange=True) if not currKeytimes: continue keytimes[d][a] = currKeytimes allKeyTimes.extend(currKeytimes) itt[d][a] = mc.keyTangent(s, attribute=a, time=(start, end), query=True, inTangentType=True) ott[d][a] = mc.keyTangent(s, attribute=a, time=(start, end), query=True, outTangentType=True) # change fixed tangents to spline, because we can't set fixed tangents for i, each in enumerate(itt[d][a]): if each == "fixed": itt[d][a][i] = "spline" for i, each in enumerate(ott[d][a]): if each == "fixed": ott[d][a][i] = "spline" # in the future, save tangent in and out values # add the start and end frames and tangents if they're not keyed if not start in keytimes[d][a]: keytimes[d][a].insert(0, start) itt[d][a].insert(0, "spline") ott[d][a].insert(0, "spline") if not end in keytimes[d][a]: keytimes[d][a].append(end) itt[d][a].append("spline") ott[d][a].append("spline") # reverse these, because we want to pop but start from the beginning itt[d][a].reverse() ott[d][a].reverse() if bakeOnOnes: allKeyTimes = range(int(start), int(end) + 1) else: allKeyTimes = list(set(allKeyTimes)) allKeyTimes.sort() with utl.UndoChunk(): with utl.IsolateViews(): for frame in allKeyTimes: # cycle through all the frames mc.currentTime(frame, edit=True) for d in destination: for a in attributes: if bakeOnOnes: mc.setKeyframe( d, attribute=a, time=frame, value=mc.getAttr(duplicates[d] + "." + a), itt="spline", ott="spline", ) elif a in keytimes[d] and frame in keytimes[d][a]: # tangent types line up with keytimes mc.setKeyframe( d, attribute=a, time=frame, value=mc.getAttr(duplicates[d] + "." + a), itt=itt[d][a].pop(), ott=ott[d][a].pop(), ) # reset time and selection mc.currentTime(resetTime, edit=True) mc.select(destination, replace=True) mc.delete(duplicates.values()) mc.filterCurve(mc.listConnections(destination, type="animCurve")) if bakeOnOnes: mc.keyTangent(destination, attribute=attributes, itt="spline", ott="spline")
def switchSpace(nodes=None, toSpace=None, switchRange=False, bakeOnOnes=False): if not toSpace: return sel = None if not nodes: nodes = mc.ls(sl=True) sel = nodes if switchRange: start, end = utl.frameRange() #need to support this eventually for controls which have multiple space attributes. selChan = utl.getSelectedChannels() controls = list() attributes = list() locators = list() values = list() for node in nodes: ssData = getSpaceSwitchData(node) if not ssData: continue if selChan and selChan[0] in ssData.keys(): ssAttr = selChan[0] else: #silly, but take the shortest one, as that's usually default ssAttr = min(ssData.keys(), key=len) if isinstance(toSpace, basestring): for i, e in enumerate(ssData[ssAttr]['enumValues']): if e.lower() == toSpace.lower(): value=i break elif isinstance(value, (float, int)): value = toSpace else: print 'Space value not valid:',toSpace continue controls.append(node) attributes.append(ssAttr) locators.append(mc.spaceLocator(name='TEMP#')[0]) values.append(value) if not values: return if switchRange: utl.matchBake(controls, locators) for ctrl, attr, value in zip(controls, attributes, values): if mc.keyframe(ctrl+'.'+attr, query=True, name=True): mc.cutKey(ctrl+'.'+attr, time=(start,end)) mc.setKeyframe(ctrl+'.'+attr, value=value, time=(start,end)) else: mc.setAttr(ctrl+'.'+attr, value) utl.matchBake(locators, controls) else: for ctrl, attr, value, loc in zip(controls, attributes, values, locators): mc.delete(mc.parentConstraint(ctrl, loc)) utl.setAnimValue(ctrl+'.'+attr, value) snap(ctrl, loc) mc.delete(locators) if sel: mc.select(sel)
def traceArc(space='camera'): ''' The main function for creating the arc. ''' if space not in ('world','camera'): OpenMaya.MGlobal.displayWarning('Improper space argument.') return global ML_TRACE_ARC_PREVIOUS_SELECTION global ML_TRACE_ARC_PREVIOUS_SPACE globalScale = 1 if mc.optionVar(exists='ml_arcTracer_brushGlobalScale'): globalScale = mc.optionVar(query='ml_arcTracer_brushGlobalScale') #save for reset: origTime = mc.currentTime(query=True) #frame range frameRange = utl.frameRange() start = frameRange[0] end = frameRange[1] #get neccesary nodes objs = mc.ls(sl=True, type='transform') if not objs: OpenMaya.MGlobal.displayWarning('Select objects to trace') return ML_TRACE_ARC_PREVIOUS_SELECTION = objs ML_TRACE_ARC_PREVIOUS_SPACE = space cam = None nearClipPlane = None shortCam = '' if space=='camera': cam = utl.getCurrentCamera() #the arc will be placed just past the clip plane distance, but no closer than 1 unit. nearClipPlane = max(mc.getAttr(cam+'.nearClipPlane'),1) shortCam = mc.ls(cam, shortNames=True)[0] topGroup = 'ml_arcGroup' worldGrp = 'ml_arcWorldGrp' localGrp = 'ml_localGrp_'+shortCam #create nodes if not mc.objExists(topGroup): topGroup = mc.group(empty=True, name=topGroup) parentGrp = topGroup if space=='world' and not mc.objExists(worldGrp): worldGrp = mc.group(empty=True, name=worldGrp) mc.setAttr(worldGrp+'.overrideEnabled',1) mc.setAttr(worldGrp+'.overrideDisplayType',2) mc.parent(worldGrp, topGroup) parentGrp = mc.ls(worldGrp)[0] if space == 'camera': camConnections = mc.listConnections(cam+'.message', plugs=True, source=False, destination=True) if camConnections: for cc in camConnections: if '.ml_parentCam' in cc: localGrp = mc.ls(cc, o=True)[0] if not mc.objExists(localGrp): localGrp = mc.group(empty=True, name=localGrp) mc.parentConstraint(cam, localGrp) mc.setAttr(localGrp+'.overrideEnabled',1) mc.setAttr(localGrp+'.overrideDisplayType',2) mc.parent(localGrp, topGroup) mc.addAttr(localGrp, at='message', longName='ml_parentCam') mc.connectAttr(cam+'.message', localGrp+'.ml_parentCam') parentGrp = mc.ls(localGrp)[0] #group per object: group = [] for i,obj in enumerate(objs): sn = mc.ls(obj,shortNames=True)[0] name = sn.replace(':','_') groupName = 'ml_{}_arcGrp'.format(name) if mc.objExists(groupName): mc.delete(groupName) group.append(mc.group(empty=True, name=groupName)) group[i] = mc.parent(group[i],parentGrp)[0] mc.setAttr(group[i]+'.translate', 0,0,0) mc.setAttr(group[i]+'.rotate', 0,0,0) with utl.UndoChunk(): #determine the method to run. Test fast against accurate. #If fast is the same, continue with fast method. #Otherwise revert to accurate method. mc.currentTime(start) fastPoints = arcDataFast([objs[0]], parentGrp, start+1, start+1, space, nearClipPlane, cam) accuratePoints = arcDataAccurate([objs[0]], parentGrp, start+1, start+1, space, nearClipPlane, cam) points = None #if they're equivalent, continue with fast: if [int(x*1000000) for x in fastPoints[0][0]] == [int(x*1000000) for x in accuratePoints[0][0]]: points = arcDataFast([objs[0]], parentGrp, start, end, space, nearClipPlane, cam) else: points = arcDataAccurate([objs[0]], parentGrp, start, end, space, nearClipPlane, cam) #create the curves and do paint effects mc.ResetTemplateBrush() brush = mc.getDefaultBrush() mc.setAttr(brush+'.screenspaceWidth',1) mc.setAttr(brush+'.distanceScaling',0) mc.setAttr(brush+'.brushWidth',0.005) for i,obj in enumerate(objs): #setup brush for path globalScale mc.setAttr(brush+'.globalScale', globalScale) mc.setAttr(brush+'.screenspaceWidth',1) mc.setAttr(brush+'.distanceScaling',0) mc.setAttr(brush+'.brushWidth',0.003) #color for c in ('R','G','B'): color = random.uniform(0.3,0.7) mc.setAttr(brush+'.color1'+c,color) baseCurve = mc.curve(d=3,p=points[i]) #fitBspline makes a curve that goes THROUGH the points, a more accurate path curve = mc.fitBspline(baseCurve, constructionHistory=False, tolerance=0.001, name='ml_arcTracer_curve_#') mc.delete(baseCurve) #paint fx mc.AttachBrushToCurves(curve) stroke = mc.ls(sl=True)[0] mc.rename(mc.listConnections(stroke+'.brush', destination=False)[0], 'ml_arcTracer_brush_#') stroke = mc.parent(stroke,group[i])[0] mc.setAttr(stroke+'.overrideEnabled',1) mc.setAttr(stroke+'.overrideDisplayType',2) mc.setAttr(stroke+'.displayPercent',92) mc.setAttr(stroke+'.sampleDensity',0.5) mc.setAttr(stroke+'.inheritsTransform',0) mc.setAttr(stroke+'.translate',0,0,0) mc.setAttr(stroke+'.rotate',0,0,0) curve = mc.parent(curve,group[i])[0] mc.setAttr(curve+'.translate',0,0,0) mc.setAttr(curve+'.rotate',0,0,0) mc.hide(curve) #setup brush for tics if space=='camera': mc.setAttr(brush+'.brushWidth',0.008) if space=='world': mc.setAttr(brush+'.brushWidth',0.005) mc.setAttr(brush+'.color1G',0) mc.setAttr(brush+'.color1B',0) for t in range(len(points[i])): frameCurve = None if space=='camera': vec = utl.Vector(points[i][t][0],points[i][t][1],points[i][t][2]) vec*=0.98 frameCurve = mc.curve(d=1,p=[points[i][t],vec[:]]) elif space=='world': frameCurve = mc.circle(constructionHistory=False, radius=0.0001, sections=4)[0] mc.setAttr(frameCurve+'.translate', points[i][t][0], points[i][t][1], points[i][t][2]) constraint = mc.tangentConstraint(curve, frameCurve, aimVector=(0,0,1), worldUpType='scene') #mc.delete(constraint) #check for keyframe colorAttribute='color1G' if mc.keyframe(obj, time=((t+start-0.5),(t+start+0.5)), query=True): mc.setAttr(brush+'.color1R',1) else: mc.setAttr(brush+'.color1R',0) mc.AttachBrushToCurves(curve) stroke = mc.ls(sl=True)[0] thisBrush = mc.listConnections(stroke+'.brush', destination=False)[0] thisBrush = mc.rename(thisBrush, 'ml_arcTracer_brush_#') #setup keyframes for frame highlighting mc.setKeyframe(thisBrush, attribute='color1G', value=0, time=(start+t-1, start+t+1)) mc.setKeyframe(thisBrush, attribute='color1G', value=1, time=(start+t,)) stroke = mc.parent(stroke,group[i])[0] mc.hide(frameCurve) mc.setAttr(stroke+'.displayPercent',92) mc.setAttr(stroke+'.sampleDensity',0.5) frameCurve = mc.parent(frameCurve,group[i])[0] if space=='camera': mc.setAttr(stroke+'.inheritsTransform',0) mc.setAttr(stroke+'.pressureScale[1].pressureScale_Position', 1) mc.setAttr(stroke+'.pressureScale[1].pressureScale_FloatValue', 0) mc.setAttr(stroke+'.translate',0,0,0) mc.setAttr(stroke+'.rotate',0,0,0) mc.setAttr(frameCurve+'.translate',0,0,0) mc.setAttr(frameCurve+'.rotate',0,0,0) mc.currentTime(origTime, edit=True) panel = mc.getPanel(withFocus=True) try: mc.modelEditor(panel, edit=True, strokes=True) except: pass mc.select(objs,replace=True) mc.refresh()
def main(): sel = mc.ls(sl=True) if not sel: raise RuntimeError('Please select an object.') if [ x for x in sel if not mc.attributeQuery('translate', exists=True, node=x) ]: raise RuntimeError( 'Only works on transform nodes, please adjust your selection.') frameRate = utl.getFrameRate() timeFactor = 1.0 / frameRate unit = mc.currentUnit(query=True, linear=True) #default is meters distFactor = 1 if unit == 'mm': distFactor = 1000 elif unit == 'cm': distFactor = 100 elif unit == 'km': distFactor = 0.001 elif unit == 'in': distFactor = 39.3701 elif unit == 'ft': distFactor = 3.28084 elif unit == 'yd': distFactor = 1.09361 elif unit == 'mi': distFactor = 0.000621371 g = 9.8 * distFactor start, end = utl.frameRange() start = int(start) end = int(end) mc.currentTime(start) for each in sel: mc.setKeyframe(each + '.translate') startTrans = mc.getAttr(each + '.translate')[0] prevTrans = [ mc.keyframe(each, query=True, attribute=x, eval=True, time=(start - 1, ))[0] for x in ('tx', 'ty', 'tz') ] xInit = startTrans[0] - prevTrans[0] yInit = startTrans[1] - prevTrans[1] zInit = startTrans[2] - prevTrans[2] mc.cutKey(each, attribute='translate', time=(start + 0.1, end + 0.5)) mc.setKeyframe(each, attribute='translateX', time=start + 1, value=startTrans[0] + xInit) mc.setKeyframe(each, attribute='translateZ', time=start + 1, value=startTrans[2] + zInit) mc.setKeyframe(each, attribute='translateX', time=end - 1, value=startTrans[0] + (xInit * (end - start - 1))) mc.setKeyframe(each, attribute='translateZ', time=end - 1, value=startTrans[2] + (zInit * (end - start - 1))) mc.setKeyframe(each, attribute='translateX', time=end, value=startTrans[0] + (xInit * (end - start))) mc.setKeyframe(each, attribute='translateZ', time=end, value=startTrans[2] + (zInit * (end - start))) for i, f in enumerate(range(start, end + 1)): t = i * timeFactor y = startTrans[1] + (i * yInit) - (g * t * t) / 2 mc.setKeyframe(each, attribute='translateY', time=f, value=y)
def fkIkSwitch(nodes=None, switchTo=None, switchRange=False, bakeOnOnes=False): switchAttr = 'fkIkSwitch' start, end = utl.frameRange() if not nodes: nodes = mc.ls(sl=True) if not nodes: return elems = getElementsAbove(nodes) if not elems: return selection = list() bakeToLocators = list() elemDict = dict() matchLocators = list() aimLocators = list() matchTo = list() matchControls = list() pvControls = list() pvMatchTo = list() garbage = list() for elem in elems: data = fkIkData(elem) if not data: #(data['fkChain'] and data['ikControl'] and data['pvControl'] and data['baseChain'] and data['ikMatchTo']): continue elemDict[elem] = dict() #0 is fk #1 is ik fkIkState = mc.getAttr(elem+'.'+switchAttr) elemDict[elem]['switchTo'] = switchTo if switchTo == None or isinstance(switchTo, bool): if fkIkState < 0.5: elemDict[elem]['switchTo'] = 1 else: elemDict[elem]['switchTo'] = 0 if elemDict[elem]['switchTo'] == 1: #ik for x in data['ikControls']: matchLocators.append(mc.spaceLocator(name='TEMP#')[0]) matchTo.extend(data['ikMatchTo']) matchControls.extend(data['ikControls']) if data['pvControl']: pvLocs = matchPoleVectorControl(data['baseChain'][0:3], data['pvControl'], doSnap=False) matchLocators.append(mc.spaceLocator(name='TEMP#')[0]) matchTo.append(pvLocs[1]) matchControls.append(data['pvControl']) garbage.extend(pvLocs) if switchRange: keytimes = mc.keyframe(data['fkChain'], time=(start,end), query=True, timeChange=True) if keytimes: elemDict[elem]['keytimes'] = list(set(keytimes)) else: elemDict[elem]['keytimes'] = range(int(start), int(end)) #elemDict[elem]['controls'] = [data['ikControl'],data['pvControl']] elemDict[elem]['controls'] = data['ikControls'] elemDict[elem]['controls'].append(data['pvControl']) selection.extend(data['ikControls']) else: #fk for x in data['baseChain']: matchLocators.append(mc.spaceLocator(name='TEMP#')[0]) matchTo.extend(data['baseChain']) matchControls.extend(data['fkChain']) if switchRange: keytimes = mc.keyframe([data['ikControl'],data['pvControl']], time=(start,end), query=True, timeChange=True) if keytimes: elemDict[elem]['keytimes'] = list(set(keytimes)) else: elemDict[elem]['keytimes'] = range(int(start),int(end)) elemDict[elem]['controls'] = data['fkChain'] selection.append(data['fkChain'][0]) #For Debugging #for a, b in zip(matchControls, matchTo): # print a,'\t->\t',b if switchRange: utl.matchBake(matchTo, matchLocators, bakeOnOnes=True) utl.matchBake(matchLocators, matchControls, bakeOnOnes=True) else: for a, b in zip(matchLocators, matchTo): mc.delete(mc.parentConstraint(b,a)) for a, b in zip(matchControls, matchLocators): snap(a,b) for elem in elems: #keytimes if switchRange: for f in range(int(start), int(end)): if not f in elemDict[elem]['keytimes']: mc.cutKey(elemDict[elem]['controls'], time=(f,)) if mc.keyframe(elem+'.'+switchAttr, query=True, name=True): mc.cutKey(elem+'.'+switchAttr, time=(start,end)) mc.setKeyframe(elem+'.'+switchAttr, value=elemDict[elem]['switchTo'], time=(start,end)) else: mc.setAttr(elem+'.'+switchAttr, elemDict[elem]['switchTo']) else: utl.setAnimValue(elem+'.'+switchAttr, elemDict[elem]['switchTo']) garbage.extend(matchLocators) mc.delete(garbage) mc.select(selection)
def fkIkSwitch(nodes=None, switchTo=None, switchRange=False, bakeOnOnes=False): switchAttr = 'fkIkSwitch' start, end = utl.frameRange() if not nodes: nodes = mc.ls(sl=True) if not nodes: return elems = getElementsAbove(nodes) if not elems: return selection = [] bakeToLocators = [] elemDict = {} matchLocators = [] aimLocators = [] matchTo = [] matchControls = [] pvControls = [] pvMatchTo = [] garbage = [] for elem in elems: data = fkIkData(elem) if not data: continue elemDict[elem] = {} #0 is fk #1 is ik fkIkState = mc.getAttr(elem+'.'+switchAttr) elemDict[elem]['switchTo'] = switchTo if switchTo == None or isinstance(switchTo, bool): if fkIkState < 0.5: elemDict[elem]['switchTo'] = 1 else: elemDict[elem]['switchTo'] = 0 if elemDict[elem]['switchTo'] == 1: #ik #key fk controls to preserve position if switchRange: mc.setKeyframe(data['fkChain'], animated=True, insert=True, time=(start,end)) else: mc.setKeyframe(data['fkChain'], animated=True) for a, b in zip(data['ikControls'], data['ikMatchTo']): locator = mc.spaceLocator(name='TEMP#')[0] snap(locator, b) #flip the locator if the control's parent is scaled in -X if hasFlippedParent(a): mc.setAttr(locator+'.rotateX', mc.getAttr(locator+'.rotateX') + 180) matchLocators.append(locator) matchTo.extend(data['ikMatchTo']) matchControls.extend(data['ikControls']) elemDict[elem]['ikControls'] = data['ikControls'] if data['pvControl']: pvLocs = matchPoleVectorControl(data['baseChain'][0:3], data['pvControl'], doSnap=False) locator = mc.spaceLocator(name='TEMP#')[0] snap(locator, pvLocs) matchLocators.append(locator) matchTo.append(pvLocs[1]) matchControls.append(data['pvControl']) garbage.extend(pvLocs) for x in data['ikControls']: if mc.attributeQuery('poleTwist', exists=True, node=x): utl.setAnimValue(x+'.poleTwist', 0) if switchRange: keytimes = mc.keyframe(data['fkChain'], time=(start,end), query=True, timeChange=True) if keytimes: elemDict[elem]['keytimes'] = list(set(keytimes)) else: elemDict[elem]['keytimes'] = range(int(start), int(end)) elemDict[elem]['controls'] = data['ikControls'] elemDict[elem]['controls'].append(data['pvControl']) selection.extend(data['ikControls']) else: #fk #key ik controls to preserve position controls = list(data['ikControls']) controls.append(data['pvControl']) if switchRange: mc.setKeyframe(controls, animated=True, insert=True, time=(start,end)) else: mc.setKeyframe(controls, animated=True) for x in data['baseChain']: locator = mc.spaceLocator(name='TEMP#')[0] snap(locator, x) matchLocators.append(locator) matchTo.extend(data['baseChain']) matchControls.extend(data['fkChain']) if switchRange: keytimes = mc.keyframe(controls, time=(start,end), query=True, timeChange=True) if keytimes: elemDict[elem]['keytimes'] = list(set(keytimes)) else: elemDict[elem]['keytimes'] = range(int(start),int(end)) elemDict[elem]['controls'] = data['fkChain'] selection.append(data['fkChain'][0]) if switchRange: utl.matchBake(matchTo, matchLocators, bakeOnOnes=True, maintainOffset=True, start=start, end=end) #if switching to ik, reset ik control attributes for elem in elems: if elemDict[elem]['switchTo'] == 1: for x in elemDict[elem]['ikControls']: attrs = mc.listAttr(x, userDefined=True, keyable=True) for attr in attrs: if 'paceSwitch' in attr: continue if mc.getAttr(x+'.'+attr, lock=True): continue default = mc.attributeQuery(attr, listDefault=True, node=x) if not default: default = 0 elif isinstance(default, list): default = default[0] if mc.keyframe(x+'.'+attr, query=True, name=True): mc.cutKey(x+'.'+attr, time=(start, end), includeUpperBound=False) mc.setKeyframe(x+'.'+attr, time=(start,end), value=default) else: try: utl.setAnimValue(x+'.'+attr, default) except Exception: pass utl.matchBake(matchLocators, matchControls, bakeOnOnes=True, start=start, end=end) else: #if switching to ik, reset ik control attributes for elem in elems: if elemDict[elem]['switchTo'] == 1: for x in elemDict[elem]['ikControls']: attrs = mc.listAttr(x, userDefined=True, keyable=True) for attr in attrs: if 'paceSwitch' in attr: continue try: default = mc.attributeQuery(attr, listDefault=True, node=x)[0] mc.setAttr(x+'.'+attr, default) except: pass for a, b in zip(matchControls, matchLocators): snap(a,b) for elem in elems: switchPlug = elem+'.'+switchAttr #keytimes if switchRange: for f in range(int(start), int(end)): if not f in elemDict[elem]['keytimes']: mc.cutKey(elemDict[elem]['controls'], time=(f,)) if mc.keyframe(switchPlug, query=True, name=True): mc.cutKey(switchPlug, time=(start,end)) mc.setKeyframe(switchPlug, value=elemDict[elem]['switchTo'], time=(start,end)) else: mc.setAttr(switchPlug, elemDict[elem]['switchTo']) else: utl.setAnimValue(switchPlug, elemDict[elem]['switchTo']) #if keyed, set tangent type to stepped if mc.keyframe(switchPlug, query=True, name=True): #get previous key previousKeyTime = mc.findKeyframe(switchPlug, which='previous') mc.keyTangent(switchPlug, time=(previousKeyTime,), outTangentType='step') garbage.extend(matchLocators) mc.delete(garbage) mc.select(selection)
def switchSpace(nodes=None, toSpace=None, switchRange=False, bakeOnOnes=False): if not toSpace: return sel = mc.ls(sl=True) if not nodes: nodes = sel if switchRange: start, end = utl.frameRange() #need to support this eventually for controls which have multiple space attributes. selChan = utl.getSelectedChannels() controls = [] attributes = [] locators = [] values = [] for node in nodes: ssData = getSpaceSwitchData(node) if not ssData: continue if selChan and selChan[0] in ssData.keys(): ssAttr = selChan[0] else: #silly, but take the shortest one, as that's usually default ssAttr = min(ssData.keys(), key=len) if isinstance(toSpace, basestring): for i, e in enumerate(ssData[ssAttr]['enumValues']): if e.lower() == toSpace.lower(): value=i break elif isinstance(value, (float, int)): value = toSpace else: print 'Space value not valid:',toSpace continue currentValue = mc.getAttr(node+'.'+ssAttr) if currentValue == value: print '{} space already set to {}, skipping'.format(node, toSpace) continue locator = mc.spaceLocator(name='TEMP#')[0] snap(locator, node) #need to test flipped before and after switch preFlipped = hasFlippedParent(node) mc.setAttr(node+'.'+ssAttr, value) postFlipped = hasFlippedParent(node) mc.setAttr(node+'.'+ssAttr, currentValue) #flip locator if we're going to or from a mirrored space if preFlipped != postFlipped: mc.setAttr(locator+'.rotateX', mc.getAttr(locator+'.rotateX') + 180) controls.append(node) attributes.append(ssAttr) locators.append(locator) values.append(value) if not values: return if switchRange: utl.matchBake(controls, locators, maintainOffset=True) for ctrl, attr, value in zip(controls, attributes, values): if mc.keyframe(ctrl+'.'+attr, query=True, name=True): mc.cutKey(ctrl+'.'+attr, time=(start,end)) mc.setKeyframe(ctrl+'.'+attr, value=value, time=(start,end)) else: mc.setAttr(ctrl+'.'+attr, value) utl.matchBake(locators, controls) else: for ctrl, attr, value, loc in zip(controls, attributes, values, locators): utl.setAnimValue(ctrl+'.'+attr, value) snap(ctrl, loc) mc.delete(locators) if sel: mc.select(sel)
def main(): sel = mc.ls(sl=True) if not sel: raise RuntimeError('Please select an object.') if [x for x in sel if not mc.attributeQuery('translate', exists=True, node=x)]: raise RuntimeError('Only works on transform nodes, please adjust your selection.') frameRate = utl.getFrameRate() timeFactor = 1.0/frameRate unit = mc.currentUnit(query=True, linear=True) #default is meters distFactor = 1 if unit == 'mm': distFactor = 1000 elif unit == 'cm': distFactor = 100 elif unit == 'km': distFactor = 0.001 elif unit == 'in': distFactor = 39.3701 elif unit == 'ft': distFactor = 3.28084 elif unit == 'yd': distFactor = 1.09361 elif unit == 'mi': distFactor = 0.000621371 g = 9.8 * distFactor start, end = utl.frameRange() start = int(start) end = int(end) mc.currentTime(start) for each in sel: mc.setKeyframe(each+'.translate') startTrans = mc.getAttr(each+'.translate')[0] prevTrans = [mc.keyframe(each, query=True, attribute=x, eval=True, time=(start-1,))[0] for x in ('tx','ty','tz')] xInit = startTrans[0]-prevTrans[0] yInit = startTrans[1]-prevTrans[1] zInit = startTrans[2]-prevTrans[2] mc.cutKey(each, attribute='translate', time=(start+0.1,end+0.5)) mc.setKeyframe(each, attribute='translateX', time=start+1, value=startTrans[0]+xInit) mc.setKeyframe(each, attribute='translateZ', time=start+1, value=startTrans[2]+zInit) mc.setKeyframe(each, attribute='translateX', time=end-1, value=startTrans[0]+(xInit*(end-start-1))) mc.setKeyframe(each, attribute='translateZ', time=end-1, value=startTrans[2]+(zInit*(end-start-1))) mc.setKeyframe(each, attribute='translateX', time=end, value=startTrans[0]+(xInit*(end-start))) mc.setKeyframe(each, attribute='translateZ', time=end, value=startTrans[2]+(zInit*(end-start))) for i,f in enumerate(range(start,end+1)): t = i * timeFactor y = startTrans[1] + (i * yInit) - (g * t * t)/2 mc.setKeyframe(each, attribute='translateY', time=f, value=y)
def fkIkSwitch(nodes=None, switchTo=None, switchRange=False, bakeOnOnes=False): switchAttr = 'fkIkSwitch' start, end = utl.frameRange() if not nodes: nodes = mc.ls(sl=True) if not nodes: return elems = getElementsAbove(nodes) if not elems: return selection = list() bakeToLocators = list() elemDict = dict() matchLocators = list() aimLocators = list() matchTo = list() matchControls = list() pvControls = list() pvMatchTo = list() garbage = list() for elem in elems: data = fkIkData(elem) if not data: #(data['fkChain'] and data['ikControl'] and data['pvControl'] and data['baseChain'] and data['ikMatchTo']): continue elemDict[elem] = dict() #0 is fk #1 is ik fkIkState = mc.getAttr(elem+'.'+switchAttr) elemDict[elem]['switchTo'] = switchTo if switchTo == None or isinstance(switchTo, bool): if fkIkState < 0.5: elemDict[elem]['switchTo'] = 1 else: elemDict[elem]['switchTo'] = 0 if elemDict[elem]['switchTo'] == 1: #ik for x in data['ikControls']: matchLocators.append(mc.spaceLocator(name='TEMP#')[0]) matchTo.extend(data['ikMatchTo']) matchControls.extend(data['ikControls']) if data['pvControl']: pvLocs = matchPoleVectorControl(data['baseChain'][0:3], data['pvControl'], doSnap=False) matchLocators.append(mc.spaceLocator(name='TEMP#')[0]) matchTo.append(pvLocs[1]) matchControls.append(data['pvControl']) garbage.extend(pvLocs) if switchRange: keytimes = mc.keyframe(data['fkChain'], time=(start,end), query=True, timeChange=True) if keytimes: elemDict[elem]['keytimes'] = list(set(keytimes)) else: elemDict[elem]['keytimes'] = range(int(start), int(end)) #elemDict[elem]['controls'] = [data['ikControl'],data['pvControl']] elemDict[elem]['controls'] = data['ikControls'] elemDict[elem]['controls'].append(data['pvControl']) selection.extend(data['ikControls']) else: #fk for x in data['baseChain']: matchLocators.append(mc.spaceLocator(name='TEMP#')[0]) matchTo.extend(data['baseChain']) matchControls.extend(data['fkChain']) if switchRange: keytimes = mc.keyframe([data['ikControls'],data['pvControl']], time=(start,end), query=True, timeChange=True) if keytimes: elemDict[elem]['keytimes'] = list(set(keytimes)) else: elemDict[elem]['keytimes'] = range(int(start),int(end)) elemDict[elem]['controls'] = data['fkChain'] selection.append(data['fkChain'][0]) #For Debugging #for a, b in zip(matchControls, matchTo): # print a,'\t->\t',b if switchRange: utl.matchBake(matchTo, matchLocators, bakeOnOnes=True) utl.matchBake(matchLocators, matchControls, bakeOnOnes=True) else: for a, b in zip(matchLocators, matchTo): mc.delete(mc.parentConstraint(b,a)) for a, b in zip(matchControls, matchLocators): snap(a,b) for elem in elems: #keytimes if switchRange: for f in range(int(start), int(end)): if not f in elemDict[elem]['keytimes']: mc.cutKey(elemDict[elem]['controls'], time=(f,)) if mc.keyframe(elem+'.'+switchAttr, query=True, name=True): mc.cutKey(elem+'.'+switchAttr, time=(start,end)) mc.setKeyframe(elem+'.'+switchAttr, value=elemDict[elem]['switchTo'], time=(start,end)) else: mc.setAttr(elem+'.'+switchAttr, elemDict[elem]['switchTo']) else: utl.setAnimValue(elem+'.'+switchAttr, elemDict[elem]['switchTo']) garbage.extend(matchLocators) mc.delete(garbage) mc.select(selection)