6
$\begingroup$

I have an object with several keyframes at different times. there is an option to grab all keyframes and snap the first (or the last) keyframe to the position of cursor? (like after effect when hit shift)

$\endgroup$
6
$\begingroup$

Align selected keys around the current frame

The following script adds Key | Align menu items with the desired functionality.

import bpy

class ANIM_OT_Align_frames(bpy.types.Operator):
    bl_idname = "action.align_frames"
    bl_label = "Align selected keys around current frame"
    bl_options = {"REGISTER", "UNDO",}

    align_end = bpy.props.BoolProperty(name="Align End")

    def execute(self, context):
        if context.space_data.type in ("DOPESHEET_EDITOR", "GRAPH_EDITOR",):
            points = []
            if context.space_data.dopesheet.show_only_selected:
                objects = context.selected_objects
            else:
                objects = context.scene.objects
            for obj in objects:
                if hasattr(obj.animation_data, "action"):
                    for fcurve in obj.animation_data.action.fcurves:
                        if fcurve.lock or (fcurve.hide and context.space_data.type == "GRAPH_EDITOR"):
                            continue
                        for keyframe_point in fcurve.keyframe_points:
                            if keyframe_point.select_control_point:
                                points.append(keyframe_point)

            if points:
                current_frame = context.scene.frame_current
                x_positions = (p.co[0] for p in points)
                offset = max(x_positions) if self.align_end else min(x_positions)
                for point in points:
                    point.co[0] += current_frame - offset
                return {"FINISHED"}
        return {"CANCELLED"}

class ANIM_MT_Align(bpy.types.Menu):
    bl_label = "Align"
    bl_idname = "action.align_frames"

    def draw(self, context):
        layout = self.layout
        layout.operator("action.align_frames", text="Selection start to current frame").align_end=False
        layout.operator("action.align_frames", text="Selection end to current frame").align_end=True

def menu(self, context):
    self.layout.menu("action.align_frames") #, icon="ALIGN")

bpy.utils.register_class(ANIM_OT_Align_frames)
bpy.utils.register_class(ANIM_MT_Align)
bpy.types.DOPESHEET_MT_key.prepend(menu)
bpy.types.GRAPH_MT_key.prepend(menu)
$\endgroup$
  • $\begingroup$ Are you planning to submit this as a patch or addon? $\endgroup$ – sambler Jul 27 '13 at 5:56
  • 1
    $\begingroup$ Hadn't planned on doing anything further with it. If there's demand, I'd be happy to do so. $\endgroup$ – Aldrik Jul 27 '13 at 10:01
  • $\begingroup$ thank for the script.I know how to embed the script in startup.blend but how can i do to run it by default ? $\endgroup$ – GabrielS Jul 29 '13 at 6:37
  • $\begingroup$ Two things come into play. In the text editor you need to tick the register tickbox next to the run script button. This option is only available if the text block name ends with .py You also need to turn on the auto run python scripts option in the preferences under the file tab. $\endgroup$ – sambler Jul 29 '13 at 7:22
  • $\begingroup$ @GabrielS Place the script in ~/.blender/2.68/scripts/startup/ with a .py file extension. See Configuration & Data Paths for more info. $\endgroup$ – Aldrik Jul 29 '13 at 9:11
7
$\begingroup$

Within the Dope Sheet and the Graph Editor you can snap the selected keyframes using the snap menu - Key->snap or Shift-S and choose one of several options.

enter image description here

You can de-select all keyframes by pressing A then use box select B to draw a box around the desired keyframes.

The DopeSheet also has 'summary lines' for example the 'Cube' line. Selecting a keyframe in a summary line will select all related keyframes.

enter image description here

Also a common method to align things in blender is to apply a scale of zero.

In the Dope Sheet selecting the keyframes you want to align and pressing S then 0 will align them all to the current frame.

In the Graph Editor you will want to ensure you only affect the frame by scaling the desired points along the x axis (S-X-0). Here they will scale to a frame between the earliest and latest selected, then you probably want to move them to the frame you want (G-X)

The same scaling trick applies to aligning almost anything. Objects in object mode (you need to make sure you turn on manipulate centre points for object alignment), vertices in edit mode, curve points, armature bones, nodes...

$\endgroup$
  • $\begingroup$ This solution will move ALL selected keyframes at the same position. I think he asked more about how to "time offset" all keyframes at once, like you can do with "G" (grab). The answer of @Aldrik seems more appropriate for this question, sry. $\endgroup$ – Polosson Jul 26 '13 at 16:36
  • 1
    $\begingroup$ Your right I did miss the snap first key part. Offsetting a specific number of frames is easy, just type the number after G $\endgroup$ – sambler Jul 27 '13 at 5:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.