2
$\begingroup$

enter image description here

Is it possible to select another / cycle through keys in the selected channel? Say I have 'Key 2' selected in XLocation and I'd like to select 'Key 1'. However, Key1 is among / close by a bunch of keys from different channels. This gets complicated quickly when you have multiple objects.

The screenshot is for a very simple animation, but you spend a lot of time trying to select the right keyframe in complicated animations.

My workflow for this purpose over the years has always been the same.

  1. Select key
  2. Hit 'L' to select Linked
  3. Invert selection with Ctrl + I
  4. Hit Tab to lock all other channels
  5. Select the desired key from among the mess
  6. Make necessary change
  7. Unlock all channels
  8. Rinse & repeat for every single time I need to do this, which is a lot during an animation session.

That is a lot of steps for such a frequent necessity. I also hate locking channels everytime.

I have looked through all available menu options and have found nothing of resemblance. I even looked through Blendermarket, for any add-on that'll help me select next / previous key in a channel via a hotkey.

I'm hoping to get a developer to maybe design a script for me with say, Shift+< for previous and Shift+> for next key in the selected channel.

Unless it already exists in Blender and is absolutely hidden?

$\endgroup$

1 Answer 1

1
$\begingroup$

you can use this code here (you should save your project before trying out this code. I didn't think of any case which might happened...i just tested it with a little example on my MBP and it worked. It might be the case that you might have to adapt the code that it works for you ...e.g. change MINUS or PLUS to NUMPAD_MINUS or NUMPAD_PLUS or vice versa. If you have a MBP it will work as it is)

import bpy

bl_info = { ## stuff so Blender can find your code
"name": "Very basic keyframe selector",
"author": "Blender.Fun",
"version": (0, 1),
"blender": (2, 90, 0),
"location": "Graph Editor > Select",
"description": "Very basic keyframe selector",
"warning": "",
"wiki_url": "",
"category": "Graph Editor",
}


def selectNext(context):
    obj = bpy.context.object       
    
    if obj:
        if obj.animation_data:
            if obj.animation_data.action:
          
                action = obj.animation_data.action   

                found = False

                for g in action.groups :
                    
                    if found:
                        break
                    
                    for channel in g.channels :  
                        if found:
                            break 
                        
                        for p in channel.keyframe_points :
                            if found:
                                p.select_control_point = True
                                break
                            if p.select_control_point:
                                p.select_control_point = False
                                found = True
                                
def selectBefore(context):
    obj = bpy.context.object      
  
    
    if obj:
        if obj.animation_data:
            if obj.animation_data.action:
          
                action = obj.animation_data.action   

                found = False

                for g in action.groups :
                    
                    if found:
                        break
                    
                    for channel in g.channels :  
                        if found:
                            break 
                        
                        for p in channel.keyframe_points :
                            
                            if found:        
                                break
                            if p.select_control_point:
                                pBefore.select_control_point = True
                                p.select_control_point = False
                                found = True
                            pBefore = p
                
    
class MYADDON_OT_SelectNext(bpy.types.Operator):
    """Tooltip"""
    bl_idname = "object.select_next"
    bl_label = "Simple select next"  
    bl_description = "My Description"
    bl_space_type = "GRAPH_EDITOR"
    bl_region_type = 'UI'

    @classmethod
    def poll(cls, context):
        return context.active_object is not None

    def execute(self, context):
        selectNext(context)
        return {'FINISHED'}

def menu_func(self, context):
    self.layout.operator(MYADDON_OT_SelectNext.bl_idname, text=MYADDON_OT_SelectNext.bl_label)

class MYADDON_OT_SelectBefore(bpy.types.Operator):
    """Tooltip"""
    bl_idname = "object.select_before"
    bl_label = "Simple select before"  
    bl_description = "My Description"
    bl_space_type = "GRAPH_EDITOR"
    bl_region_type = 'UI'

    @classmethod
    def poll(cls, context):
        return context.active_object is not None

    def execute(self, context):
        selectBefore(context)
        return {'FINISHED'}

def menu_func2(self, context):
    self.layout.operator(MYADDON_OT_SelectBefore.bl_idname, text=MYADDON_OT_SelectBefore.bl_label)


addon_keymaps = []

# Register and add to the "object" menu (required to also use F3 search "Simple Object Operator" for quick access)
def register():
    bpy.utils.register_class(MYADDON_OT_SelectNext)
    bpy.utils.register_class(MYADDON_OT_SelectBefore)
    bpy.types.GRAPH_MT_select.append(menu_func)
    bpy.types.GRAPH_MT_select.append(menu_func2)
        # Add the hotkey
    wm = bpy.context.window_manager
    kc = wm.keyconfigs.addon
    if kc:
        km = wm.keyconfigs.addon.keymaps.new(name='Graph Editor', space_type='GRAPH_EDITOR')
        kmi = km.keymap_items.new(MYADDON_OT_SelectNext.bl_idname, type='PLUS', value='PRESS', shift=True, ctrl=True)
        addon_keymaps.append((km, kmi))
        km = wm.keyconfigs.addon.keymaps.new(name='Graph Editor', space_type='GRAPH_EDITOR')
        kmi = km.keymap_items.new(MYADDON_OT_SelectBefore.bl_idname, type='NUMPAD_MINUS', value='PRESS', shift=True, ctrl=True)
        addon_keymaps.append((km, kmi))
        
def unregister():
    bpy.utils.unregister_class(MYADDON_OT_SelectNext)
    bpy.utils.unregister_class(MYADDON_OT_SelectBefore)
    bpy.types.GRAPH_MT_select.remove(menu_func)
    bpy.types.GRAPH_MT_select.remove(menu_func2)
    # Remove the hotkey
    for km, kmi in addon_keymaps:
        km.keymap_items.remove(kmi)
    addon_keymaps.clear()


if __name__ == "__main__":
    register()

    # test call
    #bpy.ops.object.select_next()

What you have to do to make it run:

  1. copy the code in your text editor

  2. tap on "Run script" enter image description here

After that, if you open the graph editor, you will have two new select entries:

enter image description here

Of course you can change the shortcut to whatever shortcut you want:

enter image description here

Here select next/before in action:

enter image description here

$\endgroup$
4
  • $\begingroup$ This is fantastic! Is there any way to make this autorun? Is there a way to compile this into a .py or something and install within Blender? I also think you should publish this somewhere noticeable, or request this to be integrated into Blender. EDIT : I ran it but unfortunately it doesn't do anything. The options appear in the Select menu, but nothing happens. What could be wrong? $\endgroup$
    – m077a
    Feb 14, 2022 at 7:22
  • $\begingroup$ Did u click on menu item or use shortcut? Try changing shortcut, if still does not work, could u provide blend file? Or the steps u r trying? $\endgroup$
    – Chris
    Feb 14, 2022 at 8:15
  • $\begingroup$ This IS a .py if you save it as .py 😉 $\endgroup$
    – Chris
    Feb 14, 2022 at 8:16
  • 1
    $\begingroup$ If 3 other agree with u - I will publish…but you were the first who wanted this here….🙃 $\endgroup$
    – Chris
    Feb 14, 2022 at 8:17

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .