162 lines
6.0 KiB
Python
162 lines
6.0 KiB
Python
|
import bpy
|
||
|
|
||
|
# https://blenderartists.org/t/how-to-execute-operator-once-when-keymap-is-held-down/1166009
|
||
|
class GPTB_OT_temp_cutter(bpy.types.Operator):
|
||
|
bl_idname = "wm.temp_cutter"
|
||
|
bl_label = "Temporary cutter"
|
||
|
bl_description = "Temporary cutter during press in GP mode"
|
||
|
bl_options = {'REGISTER'}#, 'UNDO' avoid register undo step
|
||
|
|
||
|
_is_running = False# block subsequent 'PRESS' events
|
||
|
bpy.types.Scene.tmp_cutter_org_mode = bpy.props.StringProperty(
|
||
|
name="temp cutter previous mode", description="Use to store mode used before cutter", default="")
|
||
|
# original_mode = None
|
||
|
|
||
|
def execute(self, context):
|
||
|
print('exe so cute')
|
||
|
bpy.ops.wm.tool_set_by_id(name='builtin.cutter')
|
||
|
return {'FINISHED'}
|
||
|
|
||
|
def invoke(self, context, event):
|
||
|
if event.value == 'RELEASE':
|
||
|
__class__._is_running = False
|
||
|
|
||
|
# if self.original_mode:
|
||
|
# bpy.ops.wm.tool_set_by_id(name = self.original_mode)
|
||
|
if context.scene.tmp_cutter_org_mode:
|
||
|
bpy.ops.wm.tool_set_by_id(name = context.scene.tmp_cutter_org_mode)
|
||
|
# self.original_mode = None
|
||
|
|
||
|
# return 'CANCELLED' unless the code is important,
|
||
|
# this prevents updating the view layer unecessarily
|
||
|
return {'CANCELLED'}
|
||
|
|
||
|
|
||
|
elif event.value == 'PRESS':
|
||
|
if not self._is_running:
|
||
|
# self.original_mode = bpy.context.workspace.tools.from_space_view3d_mode(bpy.context.mode, create=False).idname
|
||
|
context.scene.tmp_cutter_org_mode = bpy.context.workspace.tools.from_space_view3d_mode(bpy.context.mode, create=False).idname
|
||
|
|
||
|
__class__._is_running = True
|
||
|
return self.execute(context)
|
||
|
|
||
|
return {'CANCELLED'}
|
||
|
|
||
|
class GPTB_OT_sticky_cutter(bpy.types.Operator):
|
||
|
bl_idname = "wm.sticky_cutter"
|
||
|
bl_label = "Sticky cutter"
|
||
|
bl_description = "Sticky cutter tool"
|
||
|
bl_options = {'REGISTER'}#, 'UNDO'
|
||
|
|
||
|
def execute(self, context):
|
||
|
# toggle code
|
||
|
# if self.original_mode == 'builtin.cutter':#if on cutter, return to draw
|
||
|
# bpy.ops.wm.tool_set_by_id(name='builtin_brush.Draw')
|
||
|
return {'FINISHED'}
|
||
|
|
||
|
def modal(self, context, event):
|
||
|
if event.type == self.key and event.value == 'PRESS':
|
||
|
return {'RUNNING_MODAL'}
|
||
|
|
||
|
elif event.type == self.key and event.value == 'RELEASE':
|
||
|
|
||
|
if self.timeout:
|
||
|
# use release code in here
|
||
|
bpy.ops.wm.tool_set_by_id(name=self.original_mode)
|
||
|
print("released")
|
||
|
return {'FINISHED'}
|
||
|
|
||
|
wm = context.window_manager
|
||
|
wm.event_timer_remove(self.handler)
|
||
|
# return {'FINISHED'}
|
||
|
return self.execute(context)
|
||
|
|
||
|
elif event.type == 'TIMER':
|
||
|
self.timeout = True
|
||
|
wm = context.window_manager
|
||
|
wm.event_timer_remove(self.handler)
|
||
|
|
||
|
if self.timeout:
|
||
|
pass
|
||
|
# print("repeating holding down")
|
||
|
# use holding down code in here
|
||
|
# bpy.ops.wm.tool_set_by_id(name='builtin.cutter')#builtin.cutter cursor
|
||
|
|
||
|
return {'PASS_THROUGH'}
|
||
|
|
||
|
def invoke(self, context, event):
|
||
|
self.key = ''
|
||
|
#get key from keymap
|
||
|
wm = bpy.context.window_manager
|
||
|
#addons : #wm.keyconfigs.addon.keymaps.items()
|
||
|
for cat, keymap in wm.keyconfigs.user.keymaps.items():#user set
|
||
|
for k in keymap.keymap_items:
|
||
|
if k.idname == 'wm.sticky_cutter':
|
||
|
self.key = k.type
|
||
|
if not self.key:
|
||
|
self.report({'ERROR'}, 'Could not found dedicated key in user keymap for "wm.sticky_cutter"')
|
||
|
return {'CANCELLED'}
|
||
|
|
||
|
self.original_mode = bpy.context.workspace.tools.from_space_view3d_mode(bpy.context.mode, create=False).idname
|
||
|
if event.value == 'PRESS':
|
||
|
self.timeout = False
|
||
|
wm = context.window_manager
|
||
|
wm.modal_handler_add(self)
|
||
|
bpy.ops.wm.tool_set_by_id(name='builtin.cutter')
|
||
|
self.handler = wm.event_timer_add(
|
||
|
time_step=0.2, window=context.window)
|
||
|
return {'RUNNING_MODAL'}
|
||
|
return {'CANCELLED'}
|
||
|
|
||
|
|
||
|
## keymaps
|
||
|
'''
|
||
|
tmp_cutter_addon_keymaps = []
|
||
|
def register_keymaps():
|
||
|
# pref = get_addon_prefs()
|
||
|
# if not pref.temp_cutter_use_shortcut:
|
||
|
# return
|
||
|
|
||
|
addon = bpy.context.window_manager.keyconfigs.addon
|
||
|
|
||
|
try:
|
||
|
km = bpy.context.window_manager.keyconfigs.addon.keymaps["3D View"]# Grease Pencil
|
||
|
except Exception as e:
|
||
|
km = addon.keymaps.new(name = "3D View", space_type = "VIEW_3D") #3D View
|
||
|
pass
|
||
|
|
||
|
ops_id = 'wm.temp_cutter'# 'wm.sticky_cutter'
|
||
|
if ops_id not in km.keymap_items:
|
||
|
## keymap to operator cam space (in grease pencil mode only ?)
|
||
|
km = addon.keymaps.new(name='3D View', space_type='VIEW_3D')#EMPTY #Grease Pencil #3D View
|
||
|
|
||
|
# use 'ANY' to map both 'PRESS' and 'RELEASE' to the operator
|
||
|
# then use the operator's invoke to deal with each articulation
|
||
|
kmi = km.keymap_items.new(ops_id, type="T", value="ANY")#, alt=pref.use_alt, ctrl=pref.use_ctrl, shift=pref.use_shift, any=False)
|
||
|
tmp_cutter_addon_keymaps.append(km)
|
||
|
|
||
|
def unregister_keymaps():
|
||
|
# wm = bpy.context.window_manager
|
||
|
for km in tmp_cutter_addon_keymaps:
|
||
|
for kmi in km.keymap_items:
|
||
|
km.keymap_items.remove(kmi)
|
||
|
# wm.keyconfigs.addon.keymaps.remove(km)#dont use new km field...
|
||
|
tmp_cutter_addon_keymaps.clear()
|
||
|
# del tmp_cutter_addon_keymaps[:]
|
||
|
'''
|
||
|
|
||
|
def register():
|
||
|
if not bpy.app.background:
|
||
|
bpy.utils.register_class(GPTB_OT_temp_cutter)
|
||
|
bpy.utils.register_class(GPTB_OT_sticky_cutter)
|
||
|
# register_keymaps()
|
||
|
|
||
|
def unregister():
|
||
|
if not bpy.app.background:
|
||
|
# unregister_keymaps()
|
||
|
bpy.utils.unregister_class(GPTB_OT_temp_cutter)
|
||
|
bpy.utils.unregister_class(GPTB_OT_sticky_cutter)
|
||
|
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
register()
|