def setKey(insert=True, useSelectedCurves=True): """Sets clever keys. Hohoho. If the mouse is over the graph editor, it keys the attributes selected there. Otherwise it keys the attributes selected in the channel box. If the channelBox is closed it will key all the attributes on the selected node. It attempts to use the "Insert Key" function which makes keys match the curvature of the surrounding keys whenever possible. Set insert parameter to false to disable this behavior.""" # Get Attributes attributes = selectedAttributes.get(detectionType="cursor", useSelectedCurves=useSelectedCurves) currentFrame = cmd.currentTime(q=1) # Make extra sure attributes are unique (they should already be) attributes = list(set(attributes)) if cmd.optionVar(ex="animBlendingOpt") and cmd.optionVar(q="animBlendingOpt") == 0: # PairBlend creation is disabled. All incomming connections on # attributes will spit out warnings if we try to key them. removeConnectedAttributes(attributes) attrCount = 0 for attr in attributes: # Test if we can use insert # canInsert returns 2 if something errored out in it. insertAttr = insert canInsert = canInsertKey(attr) if canInsert != 2: if not (insert and canInsert): insertAttr = False # Key it try: performSelect = selectNewKeyframe(attr) cmd.setKeyframe(attr, i=insertAttr) attrCount += 1 # Select it if in between selected keys, or if adding # new keys and the last one was selected. if performSelect: cmd.selectKey(attr, add=1, k=1, t=(currentFrame, currentFrame)) except RuntimeError as err: print err om.MGlobal.displayError("Could not not set a key on %s." % attr) if attrCount: om.MGlobal.displayInfo("Set %d keys." % attrCount) else: om.MGlobal.displayInfo("No keys were set.")
def zeroSelection(): '''Reset the selected channels to their default values.''' # Get Attributes attributes = selectedAttributes.get(detectionType='cursor', animatableOnly=False) # Make extra sure attributes are unique (they should already be) attributes = list(set(attributes)) for attr in attributes: try: # Get default values default = cmd.attributeQuery(attr.split('.')[-1], node=attr.split('.')[0], listDefault=1) if isinstance(default, collections.Iterable) and len(default): try: cmd.setAttr(attr, default[0]) except RuntimeError: # Maybe a compound? om.MGlobal.displayError("Sorry, but I couldn't reset the attribute: %s" % attr) else: # Probably a string or something weird. Actually, I'm # curious. So I want to know what would fail.. om.MGlobal.displayError("Sorry, but I don't know how to deal with the attribute: %s" % attr) except RuntimeError: # Print out error so I can debug any further problems if # they appear... om.MGlobal.displayError("Sorry, what is this? %s" % attr)
def loadKeys(reload=0): # This function loads the currently selected keys. It can be called # explicitly with reload = 1 or implicitly from other functions. It # also tests if these new keys are the same as the old ones and # compares their values against the old ones. If they have changed # it updates the keys, making things seamless and automatic for the # user. This is so the user doesn't manually have to press a # "Reload Keys" button. # If the user is in the middle of sliding the slider or if there is # a manual reload button and it has NOT been pushed then skip # everything. global settings if settings.manualReload and not reload or settings.sliding: return newKeys = {} consecutive = True # Get keys for each attribute. keys = {} allKeys = {} selectedKeys = True attrs = [] # Find selected keyframes if graph editor is open. if selectedAttributes.isGraphEditorVisible(): attrs = cmd.keyframe(q=1, n=1, sl=1) # If none are selected, get any keys on the current frame that are # selected in the graph editor. If the graph editor isn't open, get # what is selected in the channel box if attrs: for attr in attrs: keys[attr] = cmd.keyframe(attr, q=1, iv=1, sl=1) allKeys[attr] = cmd.keyframe(attr, q=1, iv=1) elif settings.findCurrentKeys: # Get selected attributes = selectedAttributes.get(detectionType='panel') # Get keyframe attrs from selected (Basically turns . to _ and # expands single objects to object attributes) attrs = [] for att in attributes: att = cmd.keyframe(att, q=1, n=1) # Attributes can sometimes be None for some reason... So # check that. if att: attrs.extend(att) attrs = list(set(attrs)) if attrs: # Find keyframes on current time. If there are, add them to # keys time = cmd.currentTime(q=1) for attr in attrs: ky = cmd.keyframe(attr, q=1, iv=1, t=(time, time)) if ky: keys[attr] = ky allKeys[attr] = cmd.keyframe(attr, q=1, iv=1) attrs = keys.keys() selectedKeys = False if not attrs: # No keys selected, and none under the current frame. Clear keys # so we don't operate later on them when nothing is selected. settings.keys = {} if attrs: changed = 0 gKeys = settings.keys for attr in attrs: if keys[attr]: keys[attr].sort() allKeys[attr].sort() if not isConsecutive(keys[attr]): consecutive = False # elif keys[attr][0] > allKeys[attr][0] or keys[attr][-1] < allKeys[attr][-1]: else: first = 1 last = 1 if keys[attr][0] == allKeys[attr][0]: first = 0 if keys[attr][-1] == allKeys[attr][-1]: last = 0 keys[attr].insert(0, keys[attr][0] - first) keys[attr].append(keys[attr][-1] + last) newKeys[attr] = [] # Get default value realNode = cmd.listConnections('%s.output' % attr, d=1, s=0, scn=1, p=1)[0].split('.') default = cmd.attributeQuery(realNode[1], node=realNode[0], listDefault=1)[0] # Test if keys are the same. The test is in this # section for efficiency. Sorry it's less readable. keyExisted = attr in gKeys.keys() if not keyExisted or len(keys[attr]) != len(gKeys[attr]): changed = 1 for x, key in enumerate(keys[attr]): newKeys[attr].append({}) newKeys[attr][x]['key'] = key newKeys[attr][x]['value'] = cmd.keyframe(attr, index=(key, key), q = 1, valueChange = 1)[0] newKeys[attr][x]['time'] = cmd.keyframe(attr, index=(key, key), q = 1, timeChange = 1)[0] newKeys[attr][x]['default'] = default newKeys[attr][x]['endKey'] = (x == 0 and len(keys[attr]) > 1 and keys[attr][x + 1] == key) or (x == len(keys[attr]) - 1 and keys[attr][x - 1] == key) newKeys[attr][x]['lastValue'] = newKeys[attr][x]['value'] if not changed and not reload: # If keys are not on the same frame they have changed if gKeys[attr][x]['key'] != key: changed = 1 # If key is a start or end key and matches # the next or previous key, it is a # duplicate made on purpose. lastValue will # be changed on the real key in the middle. # So the value check needs to be avoided for # these duplicates. These duplicates are # made so that start and end keys can still # be manipulated. if not newKeys[attr][x]['endKey']: # If keys do not have the same value, they have changed. if round(gKeys[attr][x]['lastValue'], 5) != round(newKeys[attr][x]['value'], 5): changed = 1 # Test if keys have changed. If they have, reload them and set their defaults. if newKeys and not reload: if gKeys and not changed: if sorted(gKeys.keys()) != sorted(newKeys.keys()): changed = 1 if not changed: # Don't do anything else, these are the same keys and # the user hasn't touched them. return # Keys will get reloaded beyond this point! settings.shrinkWarning = False # Find additional information needed for Shrink and Level function if newKeys: # Find Level Value and set the linear goals level = 0 count = 0 for attr in newKeys: startKey = newKeys[attr][0] endKey = newKeys[attr][-1] for key in range(1, len(newKeys[attr]) - 1): # Sum levels level += newKeys[attr][key]['value'] count += 1 # Linear goal # Find the value that is the linear interpolation of the # start key to the end key at the current frame totalTime = float(endKey['time'] - startKey['time']) try: t = (newKeys[attr][key]['time'] - startKey['time']) / totalTime except ZeroDivisionError: t = 0.0 goal = (t * (endKey['value'] - startKey['value'])) + startKey['value'] newKeys[attr][key]['linear'] = goal if count > 0: level /= count # Find out how many keys per attribute for shrink, and add level # to each key (it's the same value, but it doesn't make sense to # put it on a lower level) keys = [] for attr in newKeys.keys(): keys.append(len(newKeys[attr])) for key in newKeys[attr]: key['level'] = level center = [] if len(set(keys)) == 1: count = [] for attr in newKeys.keys(): for x in range(len(newKeys[attr]) - 2): if len(center) <= x: center.append(0) count.append(0) center[x] += newKeys[attr][x + 1]['value'] count[x] += 1 for x in range(len(center)): center[x] /= count[x] # Add shrink to newKeys for attr in newKeys.keys(): for x in range(len(newKeys[attr]) - 2): if center: newKeys[attr][x + 1]['shrink'] = center[x] else: newKeys[attr][x + 1]['shrink'] = None # Let user know that shrink won't work. if not center: om.MGlobal.displayInfo('Shrink will not work for this selection. Select the same number of keys for every attribute for shrink to work.') settings.keys = newKeys # Reset the GUI if appropriate. if reload and settings.absolute: updateSliderGui(0) # Update GUI or print warnings/errors if settings.keys: if not selectedKeys: om.MGlobal.displayInfo('Grabbed keys from current frame.') if not consecutive: om.MGlobal.displayWarning('All selected keys must be consecutive.') elif not settings.keys: om.MGlobal.displayError('You must select at least one key!')