gp_toolbox/OP_keyframe_jump.py

177 lines
6.2 KiB
Python
Raw Normal View History

import bpy
from .utils import get_addon_prefs
class GPTB_OT_jump_gp_keyframe(bpy.types.Operator):
bl_idname = "screen.gp_keyframe_jump"
bl_label = "Jump to GPencil keyframe"
bl_description = "Jump to prev/next keyframe on active and selected layers of active grease pencil object"
bl_options = {"REGISTER"}
@classmethod
def poll(cls, context):
return context.object and context.object.type == 'GPENCIL'
next : bpy.props.BoolProperty(
name="Next GP keyframe", description="Go to next active GP keyframe", default=True)
target : bpy.props.EnumProperty(
name="Target layer", description="Choose wich layer to evaluate for keyframe change", default='ACTIVE',# options={'ANIMATABLE'}, update=None, get=None, set=None,
items=(
('ACTIVE', 'Active and selected', 'jump in keyframes of active and other selected layers ', 0),
('VISIBLE', 'Visibles layers', 'jump in keyframes of visibles layers', 1),
('ACCESSIBLE', 'Visible and unlocked layers', 'jump in keyframe of all layers', 2),
))
#(key, label, descr, id[, icon])
def execute(self, context):
if not context.object.data.layers.active:
self.report({'ERROR'}, 'No active layer on current GPencil object')
return {"CANCELLED"}
if self.target == 'ACTIVE':
gpl = [l for l in context.object.data.layers if l.select and not l.hide]
if not context.object.data.layers.active in gpl:
gpl.append(context.object.data.layers.active)
elif self.target == 'VISIBLE':
gpl = [l for l in context.object.data.layers if not l.hide]
elif self.target == 'ACCESSIBLE':
gpl = [l for l in context.object.data.layers if not l.hide and not l.lock]
current = context.scene.frame_current
p = n = None
mins = []
maxs = []
for l in gpl:
for f in l.frames:
if f.frame_number < current:
p = f.frame_number
if f.frame_number > current:
n = f.frame_number
break
mins.append(p)
maxs.append(n)
p = n = None
mins = [i for i in mins if i is not None]
maxs = [i for i in maxs if i is not None]
if mins:
p = max(mins)
if maxs:
n = min(maxs)
if self.next and n is not None:
context.scene.frame_set(n)
elif not self.next and p is not None:
context.scene.frame_set(p)
else:
self.report({'INFO'}, 'No keyframe in this direction')
return {"CANCELLED"}
return {"FINISHED"}
class KFJ_OT_rebinder(bpy.types.Operator):
bl_idname = "prefs.shortcut_rebinder"
bl_label = "rebind keyframe jump shortcut"
bl_options = {'REGISTER', 'INTERNAL'}
s_keycode: bpy.props.StringProperty()
s_ctrl: bpy.props.StringProperty()
s_shift: bpy.props.StringProperty()
s_alt: bpy.props.StringProperty()
def invoke(self, context, event):
self.prefs = get_addon_prefs()
self.init_value = getattr(self.prefs, self.s_keycode)
setattr(self.prefs, self.s_keycode, '')
context.window_manager.modal_handler_add(self)
return {'RUNNING_MODAL'}
def modal(self, context, event):
exclude_keys = {'MOUSEMOVE', 'INBETWEEN_MOUSEMOVE',
'TIMER_REPORT', 'ESC', 'WHEELUPMOUSE', 'WHEELDOWNMOUSE'}
exclude_in = ('SHIFT', 'CTRL', 'ALT')
if event.type == 'ESC':
setattr(self.prefs, self.s_keycode, self.init_value)
return {'CANCELLED'}
if event.type not in exclude_keys and not any(x in event.type for x in exclude_in):
print('key:', event.type, 'value:', event.value)
if event.value == 'PRESS':
self.report({'INFO'}, event.type)
setattr(self.prefs, self.s_shift, event.shift)
setattr(self.prefs, self.s_alt, event.alt)
setattr(self.prefs, self.s_ctrl, event.ctrl)
setattr(self.prefs, self.s_keycode, event.type)
# -# maybe add an autorebind trigger at keycode propertie level
# -# now dependent of register function within the scope of the file...
# auto_rebind()
unregister_keymaps()
register_keymaps()
context.area.tag_redraw()# seems to do nothing, have to move the mouse to update
return {'FINISHED'}
return {"RUNNING_MODAL"}
""" class KFJ_OT_rebind(bpy.types.Operator):
bl_idname = "prefs.rebind_kfj_shortcut"
bl_label = "rebind keyframe jump shortcut"
bl_options = {'REGISTER', 'INTERNAL'}
def execute(self, context):
unregister_keymaps()
register_keymaps()
return{'FINISHED'} """
addon_keymaps = []
def register_keymaps():
pref = get_addon_prefs()
if not pref.kfj_use_shortcut:
return
addon = bpy.context.window_manager.keyconfigs.addon
km = addon.keymaps.new(name = "Screen", space_type = "EMPTY")
kmi = km.keymap_items.new('screen.gp_keyframe_jump', type=pref.kfj_next_keycode, value="PRESS", alt=pref.kfj_next_alt, ctrl=pref.kfj_next_ctrl, shift=pref.kfj_next_shift, any=False)
kmi.properties.next = True
addon_keymaps.append((km, kmi))
kmi = km.keymap_items.new('screen.gp_keyframe_jump', type=pref.kfj_prev_keycode, value="PRESS", alt=pref.kfj_prev_alt, ctrl=pref.kfj_prev_ctrl, shift=pref.kfj_prev_shift, any=False)
kmi.properties.next = False
addon_keymaps.append((km, kmi))
def unregister_keymaps():
# print('UNBIND CANVAS ROTATE KEYMAPS')#Dbg
for km, kmi in addon_keymaps:
km.keymap_items.remove(kmi)
addon_keymaps.clear()
# del addon_keymaps[:]
classes = (
KFJ_OT_rebinder,
GPTB_OT_jump_gp_keyframe,
)
def register():
if not bpy.app.background:
for cls in classes:
bpy.utils.register_class(cls)
register_keymaps()
def unregister():
if not bpy.app.background:
unregister_keymaps()
for cls in reversed(classes):
bpy.utils.unregister_class(cls)