# Can someone help make this code work on all vertex groups instead of just the active one?

I have some code which works great at blurring the weights of the active vertex group but I'd like to make it blur ALL of them at one button press. I've edited the code to just try and show most of the function (which works -- on only the active vertex group) and my attempt at calling it in general (which SEEMS to work, at least in terms of time it takes, but at the end only the active one is blurred).

class BlurWeights( object ):
def __init__(self, active_index = None):

obj = bpy.context.active_object
if active_index is None:
active_index = obj.vertex_groups.active_index

# Get a BMesh representation to access connectivity information
bm_obj = bmesh.new()
bm_obj.from_mesh(obj.data)

# Find face masking.  Faces can only be found in bmesh, however,
# in paint mode vert selection is not updated correctly to edit mode
# or in bmesh, so vert selection can only be found through object.data
# I suspect this is a bug.
masked_face_verts = set([v.index for f in bm_obj.faces if f.select for v in f.verts])

weights = [1.0 for x in range(len(obj.data.vertices))]
vert_indexes = []
vert_indexes_test = []
vert_group_indexes = []
connected_verts = []
gaussian_weights = []

# Convenience function to find group index
def vert_group_index(vert, group_id):
for x, group_info in enumerate(vert.groups):
if group_info.group == group_id:
return x
return None

# Get weight info.  It's weird, I know
for vert in obj.data.vertices:
i = vert_group_index(vert, active_index)
if i is not None:
weights[vert.index] = vert.groups[i].weight

# Skip if vert is not in mask.
# Get group info
vert_indexes.append(vert.index)
vert_group_indexes.append(i)
else:
vert_indexes_test.append(vert.index)

class WeightPaintBlurAll(bpy.types.Operator):
bl_idname = "object.weightpaint_blur_all"
bl_label = "Blur"
bl_options = {'REGISTER', 'UNDO'}

settings = bpy.props.PointerProperty(type = BlurSettingsCollection)

active_index = None
blur = None

def draw(self, context):
row = self.layout.row()
row.prop(self.settings, "iterations", text = "Iter")
row = self.layout.row()
row.prop(self.settings, "selected_only")
# self.layout.prop(self, "factor")
box = self.layout.box()
row = box.row()
row.prop(self.settings, "operation", expand = True)
box = self.layout.box()
row = box.row()
row.prop(self.settings, "blur_type", expand = True)

@classmethod
def poll(cls, context):
obj = context.active_object
return (obj and obj.mode == 'WEIGHT_PAINT' and obj.type == 'MESH' and len(obj.vertex_groups) > 0)

def execute(self, context):
# Lots of addons seem to disable undo during execution.  For whatever reason,
# I had difficulty with the undo queue reliably being turned back on, so I'm leaving this out.
# global_undo_state = context.user_preferences.edit.use_global_undo
# context.user_preferences.edit.use_global_undo = False

do_gaussian = self.settings.operation == 'GAUSSIAN'

# Initialize the blur operator if it hasn't been.
if self.blur is None:
self.blur = BlurWeights( self.active_index )

self.blur.execute( iterations = self.settings.iterations,
factor = self.settings.factor, do_gaussian = do_gaussian,
blur_type = int(self.settings.blur_type),
#selected_only = self.settings.selected_only)
selected_only = False)

# This is a hack.  For some reason the active vertex group changes during execution,
# Only when used from the Blur PANEL (not the regular blur buttons in the weight paint section)
# And this seems to happen even when I touch NOTHING related to it (I tried commenting out the
# blur operation and the active_index query in invoke).  I have...no clue.
if self.active_index is not None:
context.active_object.vertex_groups.active_index = self.active_index

# context.user_preferences.edit.use_global_undo = global_undo_state
return{'FINISHED'}

def invoke(self, context, event):
for key, value in context.scene.weightpaint_blur_all_settings.items():
self.settings[key] = value
self.active_index = context.active_object.vertex_groups.active_index
return self.execute(context)


Let me add what I tried and perhaps it will focus things a bit better (I don't want development, I just want some guidance on how to proceed for someone who knows programming but is just learning Python).

I tried calling the function with what I thought would work, setting the active vertex group each time, like this:

if self.blur is None:
obj = bpy.context.object
for group in obj.vertex_groups:
bpy.ops.object.vertex_group_set_active(group=str(group.name))
self.blur = BlurWeights( self.active_index )


and it seems to be cycling, but not executing the function. Perhaps someone can tell me if I'm just doing THAT part right.

At this point I doubt if anyone can help me, since I now have the cycling part working (I think). Here's the right code if anyone happens to be playing at home:

obj = bpy.context.object
for group in obj.vertex_groups:
bpy.ops.object.vertex_group_set_active(group=str(group.name))
group_index = obj.vertex_groups[group.name].index
print( "Group=",group.name)
self.active_index = group_index
self.blur = BlurWeights( self.active_index )


This appears to work (at least it does cycle through all the groups and passes the index apparently) but the call to Blurweights, although it works fine with only the active group, does not work with this. I've emailed the author but since it was written nearly 10 years ago I doubt I'll hear back (and I've reached that dreaded programmer point where I can't even think of anything else to try. Sigh).

• Have you tried to contact the developer? Can you fix the indentation. I would vote to close this question as Mike is asking for development work and has no specifics about what is not working in the code. – J. Bakker Mar 7 '18 at 18:15
• So I tried this: if self.blur is None: obj = bpy.context.object for group in obj.vertex_groups: bpy.ops.object.vertex_group_set_active(group=str(group.name)) self.blur = BlurWeights( self.active_index ) – Mike Kelley Mar 7 '18 at 18:56
• Bakker -- I'm mostly just asking for some clarification -- perhaps I should phrase my question in a more general way, but all I want is to cycle through all the vertex groups. What I posted was how I was trying to do it, but it came out weird in comments, so I'll put it in the edit. – Mike Kelley Mar 7 '18 at 18:58
• Okay, I've edited things so hopefully it just gives folks the basic idea of what I'm trying to fix. Again, not looking to get hand holding here, just a basic point me in the right direction to try and call this thing for all vertex groups. – Mike Kelley Mar 7 '18 at 19:06
• Still the indent is incorrect. Also I miss the execute function in the blur class and the BlurSettingCollection. It is hard to point out when the posted code is not working. – J. Bakker Mar 8 '18 at 8:16