Jump to content

Keyframe moving


Milan

Recommended Posts

Hey guys. 

 

I've started working on a little toolkit to make life easier for animators but I ran into a bit of an issue. The whole thing is written in Python with Qt iterface.

 

One of the functions is simply moving keyframes on a timeline. Say I have keyframe on f10, f20 and f30. When I run the function it should shift all of them by given amount. The problem is that I can't figure out how to actually move a keyframe using python.

 

I collect keyframes from a parameter (that gives me a list of hou.Keyframe objects). Then I assumed I can just iterate through them and set new frame number. This however doesn't actually move the keyframes and if I assing the changed keyframe to it's parameter using hou.Parm.setKeyframe(keyframe) it makes a new key, but leaves the old one there as well.

 

So the questions is, am I missing something very obvious (I've been do a lot of python scripting for maya before, so maybe I just need to get my 'houdini style thinking cap' on), or am I out of luck? I could just delete the old keyframe once I create the new one, but I can't actually find anywhere in the reference, how to delete a keyframe using python in hou. 

 

This is simplified version of the code I'm using

import hou

def getKeyedParms(selected, parmList):
    for node in selected:
        parmsTemp = node.parms()
        for parm in parmsTemp:
            parm = parm.getReferencedParm()
            keyframes = parm.keyframes()
            if keyframes:
                parmList[parm] = keyframes
    return parmList

def shiftKeys(parmList, shift):
    with hou.undos.group('Shift Keys'):
        curFrame = hou.frame()
        for parm in parmList:
            for keyframe in parmList[parm]:
                if keyframe.frame() >= curFrame:
                    newTime = keyframe.frame() + shift
                    keyframe.setFrame(newTime)

selected = hou.selectedNodes()
parmList = {}

parmList = getKeyedParms(selected, parmList)
shiftKeys(parmList, 5)

Any tips appreciated. 

 

Link to comment
Share on other sites

Hi Milan,
I'm not sure if it's best workflow but I solved this by deleting all keyframes with parm.deleteAllKeyframes() and then rebuilding them.
This is my add inbetween keyframe script that shifts keyframes right or left from current timeslider position.

## add inbetween
## Petr Zloty 2014

import hou

# get all keyframes on all selected nodes
def getKeyframes(oNodes):
    keyframes = {}
    for oNode in oNodes:
        oParms = oNode.parms()
        for oParm in oParms:
             if oParm.keyframes() != ():    #if keyframe exists
                keyframes[oParm] = oParm.keyframes()
    return keyframes

#keyframes = hou.playbar.selectedKeyframes()
#recompute new keys
def inbetween(keyframes, offset):
    for parm in keyframes.keys():
        for key in keyframes[parm]:
            if hou.frame() <= key.frame():  #apply only to keys right from time cursor
                key.setFrame(key.frame()+offset)

        parm.deleteAllKeyframes()   #delete old keys

    #save new keys
    for parm in keyframes.keys():
        for key in keyframes[parm]:
            parm.setKeyframe(key)
    return True

oNodes = hou.selectedNodes()
keyframes = getKeyframes(oNodes)
inbetween(keyframes, 1) #add inbetween
#inbetween(keyframes, -1) #remove inbetween
Edited by pezetko
  • Thanks 1
Link to comment
Share on other sites

Yeah I had that as a backup option if I find that it's actually impossible to move them. Not that it's a problem deleting all keys and assigning them again. It just seem really strange that we can't actually offset them. Again maybe it's just my old maya head talking.

 

btw: looking at your code, it's very similar to my snippet, however I have a feeling that yours won't work on locked assets (e.g. most of the rigs) when your selection is controllers with published parameters. I had to use Parm.getReferencedParm() to get around that. ;)

Link to comment
Share on other sites

until Hou.Parm.stretch() and hou.Parm.stretchSubrange() get implemented, you can use their Hscript command counterpart

chkeymvhttp://www.sidefx.com/docs/houdini13.0/commands/chkeymv

 

so your shiftKeys() may look like this:

def shiftKeys(parmList, shift):
    with hou.undos.group('Shift Keys'):
        for parm in parmList:
            fRangeStart = hou.frame()
            fRangeEnd = parmList[parm][-1].frame()
            hou.hscript( "chkeymv -r %s %s %s %s %s" %(parm.path(), fRangeStart, fRangeEnd, fRangeStart + shift, fRangeEnd + shift) )

you can even use chkeymv to stretch the range or reverse, also have look at other ch* commands as they may already do stuff you want to implement 

like chls for getting animated channels, etc

Link to comment
Share on other sites

Great! 

 

That should do the trick. There are some other things I was looking for in ch* commands. I'll just need to give them a bit of icing to make them easy to use for animators. 

 

Cheers

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...