def flipPose(nodes, *args): nodes = mc.ls(nodes, long=True) flipPairs = getMirrorPairs(nodes) flipSingles = [x for x in nodes if x not in flipPairs.keys()] #do the singles: for node in flipSingles: for axis in getMirrorAxis(node): plug = '{}.{}'.format(node,axis) if mc.getAttr(plug, keyable=True): try: utl.setAnimValue(plug, mc.getAttr(plug)*-1.0) except:pass #do the pairs done = [] for node, mirror in flipPairs.items(): if node not in done: copyPose(node, mirror, flip=True) done.append(mirror)
def copyPose(fromNode, toNode, flip=False): attrs = mc.listAttr(fromNode, keyable=True) if not attrs: return #if attributes are aliased, get the real names for mirroring axis aliases = mc.aliasAttr(fromNode, query=True) if aliases: for alias, real in zip(aliases[::2], aliases[1::2]): if alias in attrs: attrs.remove(alias) attrs.append(real) axis = getMirrorAxis(toNode) for attr in attrs: if attr == 'mirrorAxis': continue if not mc.attributeQuery(attr, node=toNode, exists=True): continue fromPlug = '{}.{}'.format(fromNode, attr) toPlug = '{}.{}'.format(toNode, attr) fromValue = mc.getAttr(fromPlug) toValue = mc.getAttr(toPlug) if attr in axis: fromValue *= -1.0 toValue *= -1.0 try: utl.setAnimValue(toPlug, fromValue) except: pass if flip: try: utl.setAnimValue(fromPlug, toValue) except: pass
def copyPose(fromNode, toNode, flip=False): attrs = mc.listAttr(fromNode, keyable=True) if not attrs: return #if attributes are aliased, get the real names for mirroring axis aliases = mc.aliasAttr(fromNode, query=True) if aliases: for alias,real in zip(aliases[::2],aliases[1::2]): if alias in attrs: attrs.remove(alias) attrs.append(real) axis = getMirrorAxis(toNode) for attr in attrs: if attr == 'mirrorAxis': continue if not mc.attributeQuery(attr, node=toNode, exists=True): continue fromPlug = '{}.{}'.format(fromNode, attr) toPlug = '{}.{}'.format(toNode, attr) fromValue = mc.getAttr(fromPlug) toValue = mc.getAttr(toPlug) if attr in axis: fromValue *= -1.0 toValue *= -1.0 try: utl.setAnimValue(toPlug, fromValue) except:pass if flip: try: utl.setAnimValue(fromPlug, toValue) except:pass
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 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 = [] 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 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)