def doEditPivotDriver(self, *args): newValue = mc.floatSliderButtonGrp(self.floatSlider, query=True, value=True) try: mc.deleteUI(self.pivotDriverWindow) except: pass currentValue = mc.getAttr(self.pivotDriver) if newValue == currentValue: return oldRP = mc.getAttr(self.node+'.rotatePivot')[0] mc.setAttr(self.pivotDriver, newValue) newRP = mc.getAttr(self.node+'.rotatePivot')[0] mc.setAttr(self.pivotDriver, currentValue) parentPosition = mc.group(em=True) offsetPosition = mc.group(em=True) offsetPosition = mc.parent(offsetPosition, parentPosition)[0] mc.setAttr(offsetPosition+'.translate', newRP[0]-oldRP[0], newRP[1]-oldRP[1], newRP[2]-oldRP[2]) mc.delete(mc.parentConstraint(self.node, parentPosition)) utl.matchBake(source=[self.node], destination=[parentPosition], bakeOnOnes=True, maintainOffset=False, preserveTangentWeight=False) mc.cutKey(self.pivotDriver) mc.setAttr(self.pivotDriver, newValue) mc.refresh() utl.matchBake(source=[offsetPosition], destination=[self.node], bakeOnOnes=True, maintainOffset=False, preserveTangentWeight=False, rotate=False) mc.delete(parentPosition)
def reset_pivot(*args): sel = mc.ls(sl=True) if not sel: om.MGlobal.displayWarning('Nothing selected.') return if len(sel) > 1: om.MGlobal.displayWarning('Only works on one node at a time.') return if is_pivot_connected(sel[0]): return node = sel[0] pivotPosition = mc.getAttr(node+'.rotatePivot')[0] if pivotPosition == (0.0,0.0,0.0): return tempPosition = mc.group(em=True) tempPivot = mc.group(em=True) tempPivot = mc.parent(tempPivot, node)[0] mc.setAttr(tempPivot+'.translate', 0,0,0) mc.setAttr(tempPivot+'.rotate', 0,0,0) utl.matchBake(source=[tempPivot], destination=[tempPosition], bakeOnOnes=True, maintainOffset=False, preserveTangentWeight=False, rotate=False) mc.setAttr(node+'.rotatePivot', 0,0,0) utl.matchBake(source=[tempPosition], destination=[node], bakeOnOnes=True, maintainOffset=False, preserveTangentWeight=False, rotate=False) mc.delete(tempPosition,tempPivot) mc.select(node)
def reset_pivot(*args): sel = mc.ls(sl=True) if not sel: om.MGlobal.displayWarning('Nothing selected.') return if len(sel) > 1: om.MGlobal.displayWarning('Only works on one node at a time.') return node = sel[0] driver = None driver_value = None driver_default = None if is_pivot_connected(node): driver = pivot_driver_attr(node) if driver: dNode,dAttr = driver.split('.',1) driver_value = mc.getAttr(driver) driver_default = mc.attributeQuery(dAttr, node=dNode, listDefault=True)[0] if driver_default == driver_value: return else: om.MGlobal.displayWarning('Pivot attribute is connected, unable to edit.') return if not driver: pivotPosition = mc.getAttr(node+'.rotatePivot')[0] if pivotPosition == (0.0,0.0,0.0): return tempPosition = mc.group(em=True) tempPivot = mc.group(em=True) tempPivot = mc.parent(tempPivot, node)[0] if driver: mc.setAttr(driver, driver_default) newRP = mc.getAttr(node+'.rotatePivot')[0] mc.setAttr(driver, driver_value) mc.setAttr(tempPivot+'.translate', *newRP) else: mc.setAttr(tempPivot+'.translate', 0,0,0) mc.setAttr(tempPivot+'.rotate', 0,0,0) utl.matchBake(source=[tempPivot], destination=[tempPosition], bakeOnOnes=True, maintainOffset=False, preserveTangentWeight=False, rotate=False) if driver: mc.setAttr(driver, driver_default) else: mc.setAttr(node+'.rotatePivot', 0,0,0) mc.refresh() utl.matchBake(source=[tempPosition], destination=[node], bakeOnOnes=True, maintainOffset=False, preserveTangentWeight=False, rotate=False) mc.delete(tempPosition,tempPivot) mc.select(node)
def matchBakeLocators(parent=None, bakeOnOnes=False, constrainSource=False): #get neccesary nodes objs = mc.ls(sl=True) if not objs: OpenMaya.MGlobal.displayWarning('Select an Object') return locs = list() cutIndex = dict() noKeys = list() noKeysLoc = list() for obj in objs: name = mc.ls(obj, shortNames=True)[0] if ':' in name: name = obj.rpartition(':')[-1] locator = mc.spaceLocator(name='worldBake_'+name+'_#')[0] mc.setAttr(locator+'.rotateOrder', 3) mc.addAttr(locator, longName='ml_bakeSource', attributeType='message') mc.connectAttr('.'.join((obj,'message')), '.'.join((locator,'ml_bakeSource'))) mc.addAttr(locator, longName='ml_bakeSourceName', dataType='string') mc.setAttr('.'.join((locator,'ml_bakeSourceName')), name, type='string') if parent: locator = mc.parent(locator, parent)[0] locs.append(locator) #should look through all trans and rot if not mc.keyframe(obj, query=True, name=True): noKeys.append(obj) noKeysLoc.append(locator) utl.matchBake(objs, locs, bakeOnOnes=bakeOnOnes) if not bakeOnOnes and noKeys: utl.matchBake(noKeys, noKeysLoc, bakeOnOnes=True) if constrainSource: mc.cutKey(objs) for loc, obj in zip(locs, objs): mc.parentConstraint(loc, obj)
def fromLocators(bakeOnOnes=False): ''' Traces connections from selected locators to their source nodes, and bakes their position back. Arguments: bakeOnOnes :: Bool :: Preserve the original keytimes from the locator. ''' #get neccesary nodes objs = mc.ls(sl=True) if not objs: OpenMaya.MGlobal.displayWarning('Select a previously baked locator.') return source = list() destination = list() for src in objs: try: dest = mc.listConnections(src + '.ml_bakeSource', destination=False)[0] if dest: source.append(src) destination.append(dest) except StandardError: pass if not destination: OpenMaya.MGlobal.displayWarning('Select a previously baked locator.') return #delete constraints on destination nodes for each in destination: constraints = mc.listConnections(each, source=True, destination=False, type='constraint') if constraints: try: mc.delete(constraints) except StandardError: pass utl.matchBake(source, destination, bakeOnOnes=bakeOnOnes) for each in source: mc.delete(each)
def reset_pivot(*args): sel = mc.ls(sl=True) if not sel: om.MGlobal.displayWarning('Nothing selected.') return if len(sel) > 1: om.MGlobal.displayWarning('Only works on one node at a time.') return if is_pivot_connected(sel[0]): return node = sel[0] pivotPosition = mc.getAttr(node + '.rotatePivot')[0] if pivotPosition == (0.0, 0.0, 0.0): return tempPosition = mc.group(em=True) tempPivot = mc.group(em=True) tempPivot = mc.parent(tempPivot, node)[0] mc.setAttr(tempPivot + '.translate', 0, 0, 0) mc.setAttr(tempPivot + '.rotate', 0, 0, 0) utl.matchBake(source=[tempPivot], destination=[tempPosition], bakeOnOnes=True, maintainOffset=False, preserveTangentWeight=False, rotate=False) mc.setAttr(node + '.rotatePivot', 0, 0, 0) utl.matchBake(source=[tempPosition], destination=[node], bakeOnOnes=True, maintainOffset=False, preserveTangentWeight=False, rotate=False) mc.delete(tempPosition, tempPivot) mc.select(node)
def doEditPivotDriver(self, *args): newValue = mc.floatSliderButtonGrp(self.floatSlider, query=True, value=True) try: mc.deleteUI(self.pivotDriverWindow) except: pass currentValue = mc.getAttr(self.pivotDriver) if newValue == currentValue: return oldRP = mc.getAttr(self.node + '.rotatePivot')[0] mc.setAttr(self.pivotDriver, newValue) newRP = mc.getAttr(self.node + '.rotatePivot')[0] mc.setAttr(self.pivotDriver, currentValue) parentPosition = mc.group(em=True) offsetPosition = mc.group(em=True) offsetPosition = mc.parent(offsetPosition, parentPosition)[0] mc.setAttr(offsetPosition + '.translate', newRP[0] - oldRP[0], newRP[1] - oldRP[1], newRP[2] - oldRP[2]) mc.delete(mc.parentConstraint(self.node, parentPosition)) utl.matchBake(source=[self.node], destination=[parentPosition], bakeOnOnes=True, maintainOffset=False, preserveTangentWeight=False) mc.cutKey(self.pivotDriver) mc.setAttr(self.pivotDriver, newValue) mc.refresh() utl.matchBake(source=[offsetPosition], destination=[self.node], bakeOnOnes=True, maintainOffset=False, preserveTangentWeight=False, rotate=False) mc.delete(parentPosition)
def fromLocators(bakeOnOnes=False): ''' Traces connections from selected locators to their source nodes, and bakes their position back. Arguments: bakeOnOnes :: Bool :: Preserve the original keytimes from the locator. ''' #get neccesary nodes objs = mc.ls(sl=True) if not objs: OpenMaya.MGlobal.displayWarning('Select a previously baked locator.') return source = list() destination = list() for src in objs: try: dest = mc.listConnections(src+'.ml_bakeSource',destination=False)[0] if dest: source.append(src) destination.append(dest) except StandardError: pass if not destination: OpenMaya.MGlobal.displayWarning('Select a previously baked locator.') return #delete constraints on destination nodes for each in destination: constraints = mc.listConnections(each, source=True, destination=False, type='constraint') if constraints: try: mc.delete(constraints) except StandardError: pass utl.matchBake(source, destination, bakeOnOnes=bakeOnOnes) for each in source: mc.delete(each)
def bakeRoot(*args): ''' Transfer previously baked animation back to the root. ''' sel = mc.ls(sl=True) if not len(sel) == 1: raise RuntimeError('Please select the root control or COM locator.') root, com = getRootAndCOM(sel[0]) if not root or not com: raise RuntimeError('Could not determine root, please ensure that a COM bake setups has been previously run.') parCon = mc.listConnections(root, source=True, destination=True, type='parentConstraint') if not parCon: raise RuntimeError('Root is not constrained, transfer anim to COM node first.') src = mc.listConnections(parCon[0]+'.target[0].targetParentMatrix', source=True, destination=False) mc.delete(parCon) utl.matchBake(source=[src[0]], destination=[root], bakeOnOnes=True, maintainOffset=False, preserveTangentWeight=False, translate=True, rotate=True) for kid in mc.listRelatives(com, pa=True): if kid.split('|')[-1] == 'rootOffset': mc.delete(kid) break #reconnect constraint con = mc.listRelatives(com, type='pointConstraint', pa=True) if con: mc.cutKey(com) for a in 'XYZ': mc.connectAttr(con[0]+'.constraintTranslate'+a, com+'.translate'+a)
def parentBake(objs, parent=None, bakeOnOnes=False): #check objects can be parented parentReferenced = mc.referenceQuery(parent, isNodeReferenced=True) if parent else False culledObjs = [] for each in objs: eachParent = mc.listRelatives(each, parent=True) if mc.referenceQuery(each, isNodeReferenced=True): if parentReferenced: OpenMaya.MGlobal.displayWarning("Child and parent are both referenced, skipping: {} > {}".format(each, parent)) continue if eachParent and mc.referenceQuery(eachParent[0], isNodeReferenced=True): OpenMaya.MGlobal.displayWarning("Node is referenced and can't be reparented, skipping: {}".format(each)) continue if not parent and not eachParent: OpenMaya.MGlobal.displayWarning("Node is already child of the world, skipping: {}".format(each)) continue culledObjs.append(each) if not culledObjs: OpenMaya.MGlobal.displayWarning("No nodes could be reparented.") return source = [] destination = [] for each in culledObjs: source.append(mc.duplicate(each, parentOnly=True)[0]) mc.copyKey(each) mc.pasteKey(source[-1], option='replaceCompletely') try: if parent: destination.append(mc.parent(each, parent)[0]) else: destination.append(mc.parent(each, world=True)[0]) except RuntimeError as err: mc.delete(source) raise err utl.matchBake(source=source, destination=destination, bakeOnOnes=bakeOnOnes) mc.delete(source)
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 bakePivot(self): if not mc.objExists(self.pivotHandle) or not mc.objExists(self.node): self.cleanup() return newPivot = mc.getAttr(self.pivotHandle+'.translate')[0] if newPivot == mc.getAttr(self.node+'.rotatePivot')[0]: self.cleanup() return if not mc.keyframe(self.node, attribute=('tx','ty','tz','rx','ry','rz'), query=True, name=True): mc.setAttr(self.node+'.rotatePivot', *newPivot) self.cleanup() return tempPosition = mc.group(em=True) mc.delete(mc.parentConstraint(self.pivotHandle, tempPosition)) utl.matchBake(source=[self.node], destination=[tempPosition], bakeOnOnes=True, maintainOffset=True, preserveTangentWeight=False, rotate=False) mc.setAttr(self.node+'.rotatePivot', *newPivot) utl.matchBake(source=[tempPosition], destination=[self.node], bakeOnOnes=True, maintainOffset=False, preserveTangentWeight=False, rotate=False) mc.delete(tempPosition) mc.select(self.node) self.cleanup() #end context try: qt_maya_window.removeEventFilter(self.keypressFilter) except: pass
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 = 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 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 reset_pivot(*args): sel = mc.ls(sl=True) if not sel: om.MGlobal.displayWarning('Nothing selected.') return if len(sel) > 1: om.MGlobal.displayWarning('Only works on one node at a time.') return node = sel[0] driver = None driver_value = None driver_default = None if is_pivot_connected(node): driver = pivot_driver_attr(node) if driver: dNode, dAttr = driver.split('.', 1) driver_value = mc.getAttr(driver) driver_default = mc.attributeQuery(dAttr, node=dNode, listDefault=True)[0] if driver_default == driver_value: return else: om.MGlobal.displayWarning( 'Pivot attribute is connected, unable to edit.') return if not driver: pivotPosition = mc.getAttr(node + '.rotatePivot')[0] if pivotPosition == (0.0, 0.0, 0.0): return tempPosition = mc.group(em=True) tempPivot = mc.group(em=True) tempPivot = mc.parent(tempPivot, node)[0] if driver: mc.setAttr(driver, driver_default) newRP = mc.getAttr(node + '.rotatePivot')[0] mc.setAttr(driver, driver_value) mc.setAttr(tempPivot + '.translate', *newRP) else: mc.setAttr(tempPivot + '.translate', 0, 0, 0) mc.setAttr(tempPivot + '.rotate', 0, 0, 0) utl.matchBake(source=[tempPivot], destination=[tempPosition], bakeOnOnes=True, maintainOffset=False, preserveTangentWeight=False, rotate=False) if driver: mc.setAttr(driver, driver_default) else: mc.setAttr(node + '.rotatePivot', 0, 0, 0) mc.refresh() utl.matchBake(source=[tempPosition], destination=[node], bakeOnOnes=True, maintainOffset=False, preserveTangentWeight=False, rotate=False) mc.delete(tempPosition, tempPivot) mc.select(node)
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 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)