Simulates the object picker, it works, but it's not perfect.
Test Keymap: F7
import bpy, blf
from gpu_extras.batch import batch_for_shader
font_id = 0
class Picker(bpy.types.Operator):
bl_idname = "view3d.modal_picker"
bl_label = "Picker"
def fin(self, context, event):
bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
# restore
for obj in context.selected_objects:
obj.select_set(False)
for obj in self.old_selected_objects:
obj.select_set(True)
context.view_layer.objects.active = self.old_object
bpy.ops.object.mode_set(mode = self.old_mode)
context.window.cursor_modal_restore()
def modal(self, context, event):
context.area.tag_redraw()
self.event = event
if event.type in {'RIGHTMOUSE', 'ESC'}:
self.fin(context, event)
return {'CANCELLED'}
if event.type in {'LEFTMOUSE'}:
self.fin(context, event)
print(f"do something you want, object name = {self.blf_tx}")
return {'FINISHED'}
bpy.ops.view3d.select("INVOKE_DEFAULT", deselect_all=True)
self.blf_tx = context.selected_objects[0].name if context.selected_objects else ""
return {'RUNNING_MODAL'}
def invoke(self, context, event):
if context.space_data.type != 'VIEW_3D':
self.report({'WARNING'}, "Active space must be a View3d")
return {'CANCELLED'}
# data for restore when finish
try:
self.old_mode = context.object.mode
self.old_object = context.object
self.old_selected_objects = context.selected_objects.copy()
bpy.ops.object.mode_set(mode = 'OBJECT')
except:
return {'CANCELLED'}
self.blf_tx = ""
self.event = event
context.window.cursor_modal_set("EYEDROPPER")
self._handle = bpy.types.SpaceView3D.draw_handler_add(self.draw_callback_px, (), 'WINDOW', 'POST_PIXEL')
context.window_manager.modal_handler_add(self)
return {'RUNNING_MODAL'}
def draw_callback_px(self):
blf.color(font_id, 1.0, 1.0, 1.0, 1.0)
blf.position(font_id, self.event.mouse_region_x + 15, self.event.mouse_region_y + 30, 0)
blf.size(font_id, 20)
blf.draw(font_id, self.blf_tx)
def register():
cls = Picker
bpy.utils.register_class(cls)
# add a keymap to test. If there is a conflict with F7, choose other
key_map_type = "F7"
wm = bpy.context.window_manager
kc = wm.keyconfigs.addon
if kc:
km_name = "Window"
km = kc.keymaps[km_name] if km_name in kc.keymaps else kc.keymaps.new(name=km_name)
if not any(e.idname == cls.bl_idname for e in km.keymap_items):
kmi = km.keymap_items.new(cls.bl_idname, type=key_map_type, value='PRESS')
def unregister():
bpy.utils.unregister_class(Picker)
if __name__ == "__main__":
register()