206 lines
7.4 KiB
Python
206 lines
7.4 KiB
Python
import bpy
|
|
from .utils import get_addon_prefs
|
|
from bpy.props import BoolProperty ,EnumProperty ,StringProperty
|
|
|
|
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 == 'GREASEPENCIL'
|
|
|
|
next : BoolProperty(
|
|
name="Next GP keyframe", description="Go to next active GP keyframe",
|
|
default=True, options={'HIDDEN', 'SKIP_SAVE'})
|
|
|
|
target : EnumProperty(
|
|
name="Target layer", description="Choose wich layer to evaluate for keyframe change",
|
|
default='ACTIVE', options={'HIDDEN', 'SKIP_SAVE'},
|
|
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),
|
|
))
|
|
|
|
keyframe_type : EnumProperty(
|
|
name="Keyframe Filter", description="Jump to choosen keyframe type, else use the UI jump filter",
|
|
default='NONE', options={'HIDDEN', 'SKIP_SAVE'},
|
|
items=(
|
|
('NONE', 'Use UI Filter', '', 0), # 'KEYFRAME'
|
|
('ALL', 'All', '', 1),
|
|
('KEYFRAME', 'Keyframe', '', 'KEYTYPE_KEYFRAME_VEC', 2),
|
|
('BREAKDOWN', 'Breakdown', '', 'KEYTYPE_BREAKDOWN_VEC', 3),
|
|
('MOVING_HOLD', 'Moving Hold', '', 'KEYTYPE_MOVING_HOLD_VEC', 4),
|
|
('EXTREME', 'Extreme', '', 'KEYTYPE_EXTREME_VEC', 5),
|
|
('JITTER', 'Jitter', '', 'KEYTYPE_JITTER_VEC', 6),
|
|
('GENERATED', 'Generated', '', 'KEYTYPE_GENERATED_VEC', 7),
|
|
))
|
|
|
|
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]
|
|
|
|
if self.keyframe_type != 'NONE':
|
|
# use shortcut choice override
|
|
kftype = self.keyframe_type
|
|
else:
|
|
kftype = context.scene.gptoolprops.keyframe_type
|
|
|
|
current = context.scene.frame_current
|
|
p = n = None
|
|
|
|
mins = []
|
|
maxs = []
|
|
for l in gpl:
|
|
for f in l.frames:
|
|
# keyframe type filter
|
|
if kftype != 'ALL' and f.keyframe_type != kftype:
|
|
continue
|
|
|
|
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)
|
|
|
|
## Double the frame set to avoid refresh problem (had one in 2.91.2)
|
|
if self.next and n is not None:
|
|
context.scene.frame_set(n)
|
|
context.scene.frame_current = n
|
|
elif not self.next and p is not None:
|
|
context.scene.frame_set(p)
|
|
context.scene.frame_current = 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: StringProperty()
|
|
s_ctrl: StringProperty()
|
|
s_shift: StringProperty()
|
|
s_alt: 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_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))
|
|
|
|
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))
|
|
|
|
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) |