4
$\begingroup$

I need to select some mesh or curve from a modal operator. I can do it with mesh by using the template "Raycast View Operator" but not for the curve because they haven't got faces and the raycast return face_index. So, how can I select curves i my modal operator ?

Is there an alternative to the "Raycast View Operator" to retrieve a curve under the mouse click in a modal operator ?

$\endgroup$
4
  • 1
    $\begingroup$ can explain more please ? $\endgroup$
    – Chebhou
    May 7, 2016 at 9:36
  • $\begingroup$ i need to select some mesh or curve from a modal operator. I can do it with mesh by using the template "Raycast View Operator" but not for the curve because thet haven't got faces and the raycast return face_index. So, how can i select curves i my modal operateur ? $\endgroup$
    – pistiwique
    May 8, 2016 at 8:41
  • 1
    $\begingroup$ Could do something that checks if mouse x,y is inside the objects boundbox mapped to 2d $\endgroup$
    – batFINGER
    May 10, 2016 at 12:10
  • $\begingroup$ Yes, it's a good idea. Ill go working on it. Thank you. $\endgroup$
    – pistiwique
    May 10, 2016 at 16:02

1 Answer 1

1
$\begingroup$

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()
$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .