Creating a Pop-Up Menu to Jump to Frame

Good day Blender world,

I’ve been learning Blender vigilantly for the past four months and while focusing on animation, I have found one short-coming of Blender that I would love to help remedy.

Basically, I would love to be able to hit a keystroke that creates a pop-up menu where I can enter any frame number and jump to that frame. Seems simple enough, right? That data exists in the timeline, so why could I not retrieve that input panel anywhere in Blender (I am refering to the one between the “End Time” and the Rewind button in the timeline editor.

I have uncovered the python frame_set() command

(http://www.blender.org/documentation/blender_python_api_2_71_release/bpy.types.Scene.html#bpy.types.Scene.frame_current)

as well as the wm.context_set_enum and wm.call_menu, but I have not found a method of conjoining these lines of code together to create a shortcut pop up menu using the input panel preferences in Blender.

Any help would be much appreciated.

Thanks in advance,

Joe

Something like this:

import bpy


class MyDialog(bpy.types.Operator):

    bl_idname = "tools.mydialog"
    bl_label = "My Dialog"

    frame = bpy.props.IntProperty(name="Frame", min=0, max=300000)

    def invoke(self, context, event):
        return context.window_manager.invoke_props_dialog(self)

    def execute(self, context):
        context.scene.frame_set(self.frame)
        return {'FINISHED'}

def register():
    bpy.utils.register_module(__name__)


def unregister():
    bpy.utils.unregister_module(__name__)


if __name__ == "__main__":
    register()

    # test call
    bpy.ops.tools.mydialog('INVOKE_DEFAULT')


Wow. Thank you CoDEmanX. That’s pretty much perfect. Now, how would I then I assign a keystroke, say “cntrl+shift+spacebar” to call up that menu.

Also: would there be a way to have the data field selected by default so I could just type in my frame number rather than having to click in the field and then type it in?

I fall in love with blender over and over again each and every day and this is one of the biggest reasons why. The blender community is awesome and as soon as I am proficient enough to teach or contribute monetarily, you can count I will. I cannot wait to give back. Got to make the skills to pay the bills first and foremost though.

I was doing that 20 years ago in other software! An other thing would be great is to jump to where the cursor is in the timeline. Many time you hit pause and then you have to scroll to find where you are.

Keymaps:
http://www.blender.org/documentation/blender_python_api_2_71_release/info_tutorial_addon.html#keymap

would there be a way to have the data field selected by default

With C code yes, see the Rename marker operator

jump to where the cursor is in the timeline

Scrolling positions aren’t exposed to python, thus it can only be done with C code

import bpy



class MyDialog(bpy.types.Operator):


    bl_idname = "tools.FrameJump"
    bl_label = "Frame Jump"


    frame = bpy.props.IntProperty(name="Frame", min=0, max=300000)


    def invoke(self, context, event):
        return context.window_manager.invoke_props_dialog(self)


    def execute(self, context):
        context.scene.frame_set(self.frame)
        return {'FINISHED'}


def register():
    bpy.utils.register_module(__name__)




def unregister():
    bpy.utils.unregister_module(__name__)




if __name__ == "__main__":
    register()


    # test call
    bpy.ops.tools.mydialog('INVOKE_DEFAULT')


    # store keymaps here to access after registration
    
addon_keymaps = []


def register():
    bpy.utils.register_class(FrameJump)
    
    
    # handle the keymap
    wm = bpy.context.window_manager
    km = wm.keyconfigs.addon.keymaps.new(name='Frame Jump')


    kmi = km.keymap_items.new(FrameJump.bl_idname, 'SPACE', 'PRESS', ctrl=True, shift=True)
  


    addon_keymaps.append((km, kmi))




def unregister():


    # handle the keymap
    for km, kmi in addon_keymaps:
        km.keymap_items.remove(kmi)
    addon_keymaps.clear()

I am still having trouble getting the functionality to work. I am sure I am doing something glaringly obvious, but any ideas?

tools.FrameJump is an invalid name, like the console reports

it needs to be

 bl_idname = "tools.frame_jump"

Then you declare register() and unregister() twice for no reason, and if you use (un-)register_module(), you don’t have to register individual classes.

This fails:

     kmi = km.keymap_items.new(FrameJump.bl_idname, 'SPACE', 'PRESS', ctrl=True, shift=True)

because FrameJump is not declared, the operator class is called MyDialog.

Test call fails:

     bpy.ops.tools.mydialog('INVOKE_DEFAULT')

because you changed the bl_idname, it needs to be:

     bpy.ops.tools.frame_jump(...)

You can’t make up names for the keymap, for a global shortcut it needs to be either “Window” or “Screen”, and space_type should be ‘EMPTY’:

import bpy

class MyDialog(bpy.types.Operator):
    bl_idname = "tools.frame_jump"
    bl_label = "Frame Jump"

    frame = bpy.props.IntProperty(name="Frame", default=5, min=0, max=300000)

    def invoke(self, context, event):
        return context.window_manager.invoke_props_dialog(self)

    def execute(self, context):
        print("exec")
        context.scene.frame_set(self.frame)
        return {'FINISHED'}

    
# store keymaps here to access after registration
addon_keymaps = []

def register():
    bpy.utils.register_module(__name__)
        
    # handle the keymap
    wm = bpy.context.window_manager
    km = wm.keyconfigs.addon.keymaps.new(name='Screen', space_type='EMPTY')

    kmi = km.keymap_items.new(MyDialog.bl_idname, 'SPACE', 'PRESS', ctrl=True, shift=True)
  
    addon_keymaps.append((km, kmi))


def unregister():
    bpy.utils.unregister_module(__name__)

    # handle the keymap
    for km, kmi in addon_keymaps:
        km.keymap_items.remove(kmi)
    addon_keymaps.clear()
    
    
if __name__ == "__main__":
    register()


I am still having difficulty finding the correct code to add auto_focus to the frame field as well as adding a basic command to have return also select “ok”. Any suggestions?

You could use a props_popup instead, which should be better in terms of interaction for you:

import bpy

class MyDialog(bpy.types.Operator):
    bl_idname = "tools.frame_jump"
    bl_label = "Frame Jump"
    bl_options = {'REGISTER', 'UNDO'}

    frame = bpy.props.IntProperty(name="Frame", default=5, min=0, max=300000)

    def invoke(self, context, event):
        return context.window_manager.invoke_props_popup(self, event)

    def execute(self, context):
        print("exec")
        context.scene.frame_set(self.frame)
        return {'FINISHED'}

    
# store keymaps here to access after registration
addon_keymaps = []

def register():
    bpy.utils.register_module(__name__)
        
    # handle the keymap
    wm = bpy.context.window_manager
    km = wm.keyconfigs.addon.keymaps.new(name='Screen', space_type='EMPTY')

    kmi = km.keymap_items.new(MyDialog.bl_idname, 'SPACE', 'PRESS', ctrl=True, shift=True)
  
    addon_keymaps.append((km, kmi))


def unregister():
    bpy.utils.unregister_module(__name__)

    # handle the keymap
    for km, kmi in addon_keymaps:
        km.keymap_items.remove(kmi)
    addon_keymaps.clear()
    
    
if __name__ == "__main__":
    register()
1 Like

thks so much for this full anwser helped me for something else. a lot