1
$\begingroup$

Can you help me with simplyfy this code please? I used operations, but some skillfull user wrote that is not so good idea.

def grow_sel(Aobject,num):
    Aobject.vertex_groups.active = Aobject.vertex_groups[0]
    bpy.ops.object.mode_set(mode='OBJECT')
    bpy.ops.object.mode_set(mode='EDIT')
    bpy.ops.mesh.select_all(action='DESELECT')
    bpy.ops.object.vertex_group_select()
    for i in range(1,num):
        bpy.ops.mesh.select_more()
    bpy.ops.object.vertex_group_assign()
    bpy.ops.object.mode_set(mode='OBJECT')
    bpy.ops.object.modifier_add(type='MASK')
    bpy.context.object.modifiers["Mask"].vertex_group = obj.vertex_groups[0].name
    return("growing completed")
$\endgroup$

1 Answer 1

0
$\begingroup$

My take on this.

Sometimes it's more trouble than it's worth to completely avoid operators. Given the nature of this method I can't imagine you will be running it in a loop hundreds of times. Adding a modifier I would always use the API method. Selecting and assigning vertex groups using the operator is often the go, but you are constricted by the need to be in a certain mode for context.

Here's a method to do same, but with no operators. Can get the object from the vertex group, so that's all I pass to the method with: the number of times to grow the vertex group; and the name of the mask modifier so we don't end up adding modifiers endlessly to the stack.

I'm using a bmesh, for the ease of finding the linked faces for each vertex.

Test code, run in object mode with a mesh object having a vertex group, as context object.

import bpy
import bmesh

def mask_and_grow(vg, num=1, modname="Mask"):
    ob = vg.id_data
    mod = ob.modifiers.get(modname) or ob.modifiers.new(modname, type='MASK')
    mod.vertex_group = vg.name
    me = ob.data
    bm = bmesh.new()
    bm.from_mesh(me)
    bm.verts.ensure_lookup_table()
    def ingroup(vg, v):
        vert = me.vertices[v.index] # use either bm or me
        return vg.index in [vg.group for vg in vert.groups] 

    def grow(v):
        return (v for f in v.link_faces
                for v in f.verts
                if not ingroup(vg, v))

    vg_verts =  (bm.verts[v.index] for v in me.vertices 
            if ingroup(vg, v))    
    for i in range(num):
        # only need to look at extended next time
        vg_verts = list(set(v for g in [grow(vgv) for vgv in vg_verts] for v in g))
        vg.add([v.index for v in vg_verts],
                1.0,
                'REPLACE')  
    #me.update()
    bm.free()

# test call
ob = bpy.context.object
vg = ob.vertex_groups.active
mask_and_grow(vg, num=2)
$\endgroup$
2
  • $\begingroup$ Thank you batFINGER, I need do this 70times per puppet. (cut out puppet). Because I using parts of the puppet on the grid or plain. $\endgroup$
    – MRL
    Commented Mar 28, 2018 at 20:57
  • $\begingroup$ Every phase of ..mouth or hand, for example, is 5k*5k high for zooming the scene. And i think, if you move the uv there can be some errors with motion blur or not ? $\endgroup$
    – MRL
    Commented Apr 18, 2018 at 0:35

You must log in to answer this question.

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