1 # SPDX-FileCopyrightText: 2019-2022 Blender Foundation
3 # SPDX-License-Identifier: GPL-2.0-or-later
6 Jump X Frames on Shift Up/Down
8 When you hit Shift Up/Down, you'll jump 10 frames forward/backwards.
9 Sometimes is nice to tweak that value.
11 In the User Preferences, Editing tab, you'll find a "Frames to Jump"
12 slider where you can adjust how many frames you'd like to move
15 Make sure you save your user settings if you want to use this value from
18 Find it on the User Preferences, Editing.
22 from bpy
.types
import Operator
, Panel
23 from bpy
.props
import BoolProperty
28 # FUNCTION: Check if object has keyframes for a specific frame
29 def is_keyframe(ob
, frame
):
30 if ob
is not None and ob
.animation_data
is not None and ob
.animation_data
.action
is not None:
31 for fcu
in ob
.animation_data
.action
.fcurves
:
32 if frame
in (p
.co
.x
for p
in fcu
.keyframe_points
):
37 # monkey path is_keyframe function
38 bpy
.types
.Object
.is_keyframe
= is_keyframe
41 # FEATURE: Jump to frame in-between next and previous keyframe
42 class AMTH_SCREEN_OT_keyframe_jump_inbetween(Operator
):
43 """Jump to half in-between keyframes"""
44 bl_idname
= "screen.amth_keyframe_jump_inbetween"
45 bl_label
= "Jump to Keyframe In-between"
47 backwards
: BoolProperty()
49 def execute(self
, context
):
53 ob
= bpy
.context
.object
54 frame_start
= scene
.frame_start
55 frame_end
= scene
.frame_end
57 if not context
.scene
.get("amth_keyframes_jump"):
58 context
.scene
["amth_keyframes_jump"] = list()
60 keyframes_list
= context
.scene
["amth_keyframes_jump"]
62 for f
in range(frame_start
, frame_end
):
64 keyframes_list
= list(keyframes_list
)
65 keyframes_list
.append(f
)
68 keyframes_list_half
= []
70 for i
, item
in enumerate(keyframes_list
):
72 next_item
= keyframes_list
[i
+ 1]
73 keyframes_list_half
.append(int((item
+ next_item
) / 2))
77 if len(keyframes_list_half
) > 1:
79 v
= (scene
.frame_current
== keyframes_list_half
[::-1][-1],
80 scene
.frame_current
< keyframes_list_half
[::-1][-1])
82 self
.report({"INFO"}, "No keyframes behind")
84 for i
in keyframes_list_half
[::-1]:
85 if scene
.frame_current
> i
:
86 scene
.frame_current
= i
89 v
= (scene
.frame_current
== keyframes_list_half
[-1],
90 scene
.frame_current
> keyframes_list_half
[-1])
92 self
.report({"INFO"}, "No keyframes ahead")
94 for i
in keyframes_list_half
:
95 if scene
.frame_current
< i
:
96 scene
.frame_current
= i
99 self
.report({"INFO"}, "Object has only 1 keyframe")
101 self
.report({"INFO"}, "Object has no keyframes")
106 # FEATURE: Jump forward/backward every N frames
107 class AMTH_SCREEN_OT_frame_jump(Operator
):
108 """Jump a number of frames forward/backwards"""
109 bl_idname
= "screen.amaranth_frame_jump"
110 bl_label
= "Jump Frames"
112 forward
: BoolProperty(default
=True)
114 def execute(self
, context
):
115 scene
= context
.scene
117 get_addon
= "amaranth" in context
.preferences
.addons
.keys()
121 preferences
= context
.preferences
.addons
["amaranth"].preferences
123 if preferences
.use_framerate
:
124 framedelta
= scene
.render
.fps
126 framedelta
= preferences
.frames_jump
128 scene
.frame_current
= scene
.frame_current
+ framedelta
130 scene
.frame_current
= scene
.frame_current
- framedelta
135 class AMTH_USERPREF_PT_animation(Panel
):
136 bl_space_type
= 'PREFERENCES'
137 bl_region_type
= 'WINDOW'
138 bl_label
= "Jump Keyframes"
139 bl_parent_id
= "USERPREF_PT_animation_keyframes"
141 def draw(self
, context
):
142 preferences
= context
.preferences
.addons
["amaranth"].preferences
146 col
= layout
.column()
148 row
.label(text
="Frames to Jump")
149 row
.prop(preferences
, "frames_jump", text
="")
151 col
= layout
.column()
153 row
.label(text
="Jump Operators")
154 row
.operator(AMTH_SCREEN_OT_keyframe_jump_inbetween
.bl_idname
,
155 icon
="PREV_KEYFRAME", text
="Jump to Previous").backwards
= True
156 row
.operator(AMTH_SCREEN_OT_keyframe_jump_inbetween
.bl_idname
,
157 icon
="NEXT_KEYFRAME", text
="Jump to Next").backwards
= False
161 bpy
.utils
.register_class(AMTH_USERPREF_PT_animation
)
162 bpy
.utils
.register_class(AMTH_SCREEN_OT_frame_jump
)
163 bpy
.utils
.register_class(AMTH_SCREEN_OT_keyframe_jump_inbetween
)
165 # register keyboard shortcuts
166 wm
= bpy
.context
.window_manager
167 kc
= wm
.keyconfigs
.addon
170 km
= kc
.keymaps
.new(name
="Frames")
171 kmi
= km
.keymap_items
.new('screen.amth_keyframe_jump_inbetween', 'UP_ARROW', 'PRESS', shift
=True, ctrl
=True)
172 kmi
.properties
.backwards
= False
173 KEYMAPS
.append((km
, kmi
))
175 kmi
= km
.keymap_items
.new('screen.amth_keyframe_jump_inbetween', 'DOWN_ARROW', 'PRESS', shift
=True, ctrl
=True)
176 kmi
.properties
.backwards
= True
177 KEYMAPS
.append((km
, kmi
))
179 kmi
= km
.keymap_items
.new(
180 "screen.amaranth_frame_jump", "UP_ARROW", "PRESS", shift
=True)
181 kmi
.properties
.forward
= True
182 KEYMAPS
.append((km
, kmi
))
184 kmi
= km
.keymap_items
.new(
185 "screen.amaranth_frame_jump", "DOWN_ARROW", "PRESS", shift
=True)
186 kmi
.properties
.forward
= False
187 KEYMAPS
.append((km
, kmi
))
191 bpy
.utils
.unregister_class(AMTH_USERPREF_PT_animation
)
192 bpy
.utils
.unregister_class(AMTH_SCREEN_OT_frame_jump
)
193 bpy
.utils
.unregister_class(AMTH_SCREEN_OT_keyframe_jump_inbetween
)
195 for km
, kmi
in KEYMAPS
:
196 km
.keymap_items
.remove(kmi
)