Import_3ds: Improved distance cue node setup
[blender-addons.git] / amaranth / animation / jump_frames.py
blob15fc300ebbbcbc30bc24cbaf7d204421b595ca1e
1 # SPDX-FileCopyrightText: 2019-2022 Blender Foundation
3 # SPDX-License-Identifier: GPL-2.0-or-later
5 """
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
13 forwards/backwards.
15 Make sure you save your user settings if you want to use this value from
16 now on.
18 Find it on the User Preferences, Editing.
19 """
21 import bpy
22 from bpy.types import Operator, Panel
23 from bpy.props import BoolProperty
25 KEYMAPS = list()
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):
33 return True
34 return False
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):
50 back = self.backwards
52 scene = context.scene
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):
63 if ob.is_keyframe(f):
64 keyframes_list = list(keyframes_list)
65 keyframes_list.append(f)
67 if keyframes_list:
68 keyframes_list_half = []
70 for i, item in enumerate(keyframes_list):
71 try:
72 next_item = keyframes_list[i + 1]
73 keyframes_list_half.append(int((item + next_item) / 2))
74 except:
75 pass
77 if len(keyframes_list_half) > 1:
78 if back:
79 v = (scene.frame_current == keyframes_list_half[::-1][-1],
80 scene.frame_current < keyframes_list_half[::-1][-1])
81 if any(v):
82 self.report({"INFO"}, "No keyframes behind")
83 else:
84 for i in keyframes_list_half[::-1]:
85 if scene.frame_current > i:
86 scene.frame_current = i
87 break
88 else:
89 v = (scene.frame_current == keyframes_list_half[-1],
90 scene.frame_current > keyframes_list_half[-1])
91 if any(v):
92 self.report({"INFO"}, "No keyframes ahead")
93 else:
94 for i in keyframes_list_half:
95 if scene.frame_current < i:
96 scene.frame_current = i
97 break
98 else:
99 self.report({"INFO"}, "Object has only 1 keyframe")
100 else:
101 self.report({"INFO"}, "Object has no keyframes")
103 return {"FINISHED"}
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()
118 if not get_addon:
119 return {"CANCELLED"}
121 preferences = context.preferences.addons["amaranth"].preferences
123 if preferences.use_framerate:
124 framedelta = scene.render.fps
125 else:
126 framedelta = preferences.frames_jump
127 if self.forward:
128 scene.frame_current = scene.frame_current + framedelta
129 else:
130 scene.frame_current = scene.frame_current - framedelta
132 return {"FINISHED"}
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
144 layout = self.layout
146 col = layout.column()
147 row = col.row()
148 row.label(text="Frames to Jump")
149 row.prop(preferences, "frames_jump", text="")
151 col = layout.column()
152 row = col.row()
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
160 def register():
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
168 if kc is not None:
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))
190 def unregister():
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)
197 KEYMAPS.clear()