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$
0

2 Answers 2

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

You must log in to answer this question.

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