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$
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$
  • $\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 Mar 28 '18 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 Apr 18 '18 at 0:35

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.