def arcDataAccurate(objs, parentGrp, start, end, space, nearClipPlane, cam=None): points = [[] for x in objs] 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 = utl.Vector(objPnt[0], objPnt[1], objPnt[2]) camVec = utl.Vector(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) return points
def transferKeytimes(source, destinations): if not isinstance(destinations, (list, tuple)): destinations = [destinations] attributes = mc.listAttr(source, keyable=True, unlocked=True) keytimes = dict() start = None end = None for a in attributes: currKeytimes = mc.keyframe(source, attribute=a, query=True, timeChange=True) if not currKeytimes: continue if start == None or currKeytimes[0] < start: start = currKeytimes[0] if end == None or currKeytimes[-1] > end: end = currKeytimes[-1] keytimes[a] = currKeytimes #allKeyTimes.extend(currKeytimes) if not keytimes: return with utl.IsolateViews(): mc.bakeResults(destinations, time=(start, end), sampleBy=1, preserveOutsideKeys=True, simulation=True) #euler filter mc.filterCurve(mc.listConnections(destinations, type='animCurve')) #go through all keys and delete for k in keytimes: for f in range(int(start), int(end)): if not f in keytimes[k]: mc.cutKey(destinations, attribute=k, time=(f, ))
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 convertTo(roo='zxy'): if not roo in ROTATE_ORDERS: OpenMaya.MGlobal.displayWarning('Not a proper rotation order: ' + str(roo)) return sel = mc.ls(sl=True) if not sel: OpenMaya.MGlobal.displayWarning('Please make a selection.') return time = mc.currentTime(query=True) #check that all rot channels have keys, or no keys keytimes = dict() prevRoo = dict() allKeytimes = list() keyedObjs = list() unkeyedObjs = list() for obj in sel: rotKeys = mc.keyframe(obj, attribute='rotate', query=True, timeChange=True) if rotKeys: keytimes[obj] = list(set(rotKeys)) prevRoo[obj] = ROTATE_ORDERS[mc.getAttr(obj + '.rotateOrder')] allKeytimes.extend(rotKeys) keyedObjs.append(obj) else: unkeyedObjs.append(obj) with utl.UndoChunk(): #change rotation order for keyed objects if keyedObjs: allKeytimes = list(set(allKeytimes)) allKeytimes.sort() with utl.IsolateViews(): #set keyframes first, so that frames that aren't keyed on all channels are for frame in allKeytimes: mc.currentTime(frame, edit=True) for obj in keyedObjs: if frame in keytimes[obj]: #set keyframe to make sure every channel has a key mc.setKeyframe(obj, attribute='rotate') for frame in allKeytimes: mc.currentTime(frame, edit=True) for obj in keyedObjs: if frame in keytimes[obj]: #change the rotation order to the new value mc.xform(obj, preserve=True, rotateOrder=roo) #set a keyframe with the new rotation order mc.setKeyframe(obj, attribute='rotate') #change rotation order back without preserving, so that the next value is correct mc.xform(obj, preserve=False, rotateOrder=prevRoo[obj]) #reset current time while still isolated, for speed. mc.currentTime(time, edit=True) #set the final rotate order for keyed objects for each in keyedObjs: mc.xform(each, preserve=False, rotateOrder=roo) mc.filterCurve(each) #for unkeyed objects, rotation order just needs to be changed with xform if unkeyedObjs: for obj in unkeyedObjs: mc.xform(obj, preserve=True, rotateOrder=roo) #reset selection mc.select(sel)
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')