Maya Not Updating Selection in Python Script the Same as in Viewport

Hi,

I am writing a Maya/Python script that uses a button callback to select a control, run a script on the selection, and then advance to the next keyframe and repeat.

However, selecting a control in the viewport and selecting a control via script don’t seem to behave the same.
If I select a control in the viewport and then run a script that advances to the next keyframe, it works as I would expect.
But if the selection is cleared, and I select the same control within the script and then advance to the next keyframe, the selection gets updated but it doesn’t advance to the next keyframe.
I’ve tried forcing a refresh or force updating the viewport as part of the script but that doesn’t seem to help.

Does cmds.select() not select keyframe data? Or is the selection not fully updating until the script has finished running?
Any ideas on what I’m missing would be much appreciated?

Below is a simple UI that illustrates what I’m trying to do. It requires a single object named “body_anim” with some keyframes set on it.
If something is already selected in the viewport and I press the button it works as expected, but if I clear the selection in the viewport and then run the script it doesn’t advance to the next keyframe.


import maya.cmds as cmds

def FrameStepUI():

    windowName = "FrameStep"

    if cmds.window(windowName, exists=True):
                    cmds.deleteUI(windowName)

    window = cmds.window(windowName, title=windowName, w=100, h=100, mnb=False, mxb=False, sizeable = False)

    mainLayout = cmds.columnLayout(w=100, h=100)

    selectNextFrameBtn = cmds.button(label = "Select + Next Frame", c = selectFrameStep)

    cmds.showWindow(window)

def frameStep(*args):
    cmds.currentTime((cmds.findKeyframe(timeSlider = True, which = "next")), update = True, edit = True)

def doSomething():
    print "DO SOMETHING"

def selectCtrl():
    cmds.select("body_anim", replace = True)
    
def selectFrameStep(*args):
    selectCtrl()
    doSomething()
    frameStep()

FrameStepUI()

Someone help this man so that I can start animating in Maya with his tools!!

In the grand tradition of answering a question with a question, is there a reason you are not getting the keyframe data from the object you are selecting, rather than the time control?

For example, replacing your frameStep() func with:


def frameStep(*args):
    sel = cmds.ls(sl=True)
    frame = cmds.findKeyframe(sel[0], which = "next")
    cmds.currentTime(frame, update = True, edit = True)

I haven’t looked at when the time control actually gets updated, but I know this code snippet seems to behave how you want.

Phil

With nothing selected, if I click the button twice, it behaves correctly.

Here’s some horrible code that makes it work with one click (but will fail if you’re trying to go from the last keyframe to the first keyframe, and require two clicks…).


import maya.cmds as cmds

def FrameStepUI():

    windowName = "FrameStep"

    if cmds.window(windowName, exists=True):
                    cmds.deleteUI(windowName)

    window = cmds.window(windowName, title=windowName, w=100, h=100, mnb=False, mxb=False, sizeable = False)

    mainLayout = cmds.columnLayout(w=100, h=100)

    selectNextFrameBtn = cmds.button(label = "Select + Next Frame", c = selectFrameStep)

    cmds.showWindow(window)

def frameStep(*args):
    current_time = cmds.currentTime(query = True)       
    flagged = selectCtrl()    
    if flagged:
        next = cmds.findKeyframe('body_anim', time = (current_time, current_time), which = 'next')        
        cmds.currentTime(next, edit = True, update = True)
    cmds.currentTime((cmds.findKeyframe(timeSlider = True, which = "next")), update = True, edit = True)

def selectCtrl():
    sel = cmds.ls(selection = True)        
    flagged = False
    if len(sel) == 0:        
        flagged = True        
    cmds.select("body_anim", replace = True)
    return flagged
    
def selectFrameStep(*args):      
    frameStep()

FrameStepUI()

Thanks for the replies guys!

You’re right Phil, it looks like there is no need to get the key data from the time control and that I can just get it from the object directly. I thought for some reason I could only get the keyframe info from the time control. Oops.

So thanks for answering my question with a question. :): I’m still learning this stuff, and the question helped me think about the way I was approaching it.

It looks like my problem was in using the timeSlider flag. The timeslider doesn’t seem to get updated until after the script has finished running and forceRefreshing the time control is unnecessary if I can get the data from the object directly like you said.