0
$\begingroup$

I am trying to create a vertice at my mouse position with python. This is my code to get the location:

`       region = bpy.context.region
        space = bpy.context.space_data.region_3d
        x, y = event.mouse_region_x, event.mouse_region_x
        loc = bpy_extras.view3d_utils.region_2d_to_location_3d(region, space, (x, y), (0,0,0))

. This is what happens:enter image description here

$\endgroup$
1
$\begingroup$

Add vert on left mouse click

Further to this answer added code to add vertex on left mouse click. (Using method explained here) Added a list to class to hold the newly added vertices, as suggested via this question.

Things to note:

Vertex coordinates are local coordinates, whereas the calculated 3d cursor position is a global coordinate. To convert global to local the global vector is multiplied by the objects matrix world inverted.

A class property for the matrix world inverted, similar to setting cls.bm for bmesh to avoid inverting the matrix each time.

When writing operators or panels, very rarely (if ever) do you need to access context via bpy.context. If context is an argument use it. I often use context = bpy.context atop of test scripts as a convenient way to later copy / paste into code where context is defined.

import bpy
import bmesh
from bpy_extras.view3d_utils import region_2d_to_location_3d

bmeshes = {}

class Modal(bpy.types.Operator):
    bl_idname = "object.modal"
    bl_label = "Modal Op"
    bl_description = "Other thingy"
    bl_options = {"REGISTER"}

    bm = None
    added_verts = []

    @classmethod
    def poll(cls, context):
        return context.object and context.object.type == 'MESH'

    @classmethod
    def bmesh(cls, context):
        me = context.edit_object.data
        cls.bm = bmesh.from_edit_mesh(me)

    def invoke(self, context, event):
        bpy.ops.object.mode_set(mode='EDIT')
        self.bmesh(context)
        context.window_manager.modal_handler_add(self)
        return {"RUNNING_MODAL"}

    def add_vert(self, loc):
        v = self.bm.verts.new(loc)
        self.added_verts.append(v)

        return v

    def modal(self, context, event):
        # no longer in edit mode
        if context.mode != 'EDIT_MESH':
            self.bm.free()
            self.bm = None
            return {'CANCELLED'}
        ob = context.edit_object
        me = ob.data
        if self.bm is None or not self.bm.is_valid:
            # in edit mode so try make a new bmesh
            self.bmesh(context)            
        if event.type == "LEFTMOUSE" and event.value == "PRESS":

            x, y = event.mouse_region_x, event.mouse_region_y
            region = context.region
            rv3d = context.space_data.region_3d

            loc = region_2d_to_location_3d(region, rv3d, (x, y), (0, 0, 0))        

            v = self.add_vert(ob.matrix_world.inverted() * loc)
            v.select = True

        if event.type in {"RIGHTMOUSE", "ESC"}:
            self.bm.verts.index_update()
            bmesh.update_edit_mesh(me)
            print("added", self.added_verts)            
            return {"CANCELLED"}

        if event.type in ["WHEELUPMOUSE","WHEELDOWNMOUSE","MIDDLEMOUSE","LEFTMOUSE"]:
            return{"PASS_THROUGH"}

        return {"RUNNING_MODAL"}

def register():
    bpy.utils.register_class(Modal)

def unregister():
    bpy.utils.unregister_class(Modal)

if __name__ == "__main__":
    register()

Btw. If you put minimal working code into your question it would be a lot easier to work out where your particular mistake is.

| improve this answer | |
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.