3
$\begingroup$

I need to know the current active vertex from within a Handler, so i do this:

import bpy, bmesh
from bpy.app.handlers import persistent

def find_active_vertex(bm):
    elem = next(reversed(bm.select_history), None)
    if isinstance(elem, bmesh.types.BMVert):
        return elem
    return None

@persistent
def edit_object_change_handler(scene):

    context = bpy.context
    obj=context.edit_object
    if obj and obj.type=="MESH" and context.mode=="EDIT_MESH":
        bm = bmesh.from_edit_mesh(obj.data)
        avi = find_active_vertex(bm)
        if avi:
            # ... more done here ...
            pass

def register():
    bpy.app.handlers.scene_update_post.append(edit_object_change_handler)

However this approach does not work. The following line seems to create a very unwanted misbehavior of Blender:

elem = next(reversed(bm.select_history), None)

As soon as i add this statement the weight editor in the "n" panel of the 3D View no longer accepts weight values as input.

So my question is: Is there an alternative to find the active Vertex within a Handler that does not affect the behavior of the Vertex Weights panel within the "n" properties sidebar of the 3D View ?

$\endgroup$
2
$\begingroup$

Try reusing the bmesh instance, here I've used a global dic. Also I've used history.active

import bpy, bmesh
from bpy.app.handlers import persistent

def find_active_vertex(bm):

    elem = bm.select_history.active
    if elem is not None and  isinstance(elem, bmesh.types.BMVert):
        print("BVert", elem, elem.index)
        return elem
    return None

dic = {}
@persistent
def edit_object_change_handler(scene):

    obj = scene.objects.active
    if obj is None:
        return None

    if obj.mode == 'EDIT' and obj.type == 'MESH':
        bm = dic.setdefault(obj.name, bmesh.from_edit_mesh(obj.data))
        find_active_vertex(bm)
        return None

    dic.clear()
    return None

def register():
    bpy.app.handlers.scene_update_post.append(edit_object_change_handler)

register()

scene_update handlers are called around 200 times per second, (Sample file here https://developer.blender.org/T46329 ) Using the data to load bmesh that many times probably affected the vertex weight panel. I'd consider using a modal timer operator instead.

$\endgroup$
0
$\begingroup$

Just use bm.select_history[-1]. Also account for the chance that this raises an IndexError when the list is empty, of course.

$\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.