In edit mode If I manually select a vertex group and highlight one vertice, I can open this, manually fill out the values, and hit copy. All the vertices in the group will then receive the vertex weights shown. Can this be done with Python?
I do have an array of indices: verts_in_group = [551, 556, 662, 664, 698, 2220, 2230, 2236]
so I'm not concerned about having to find them. I assume you can reference the bones by name, since they are already named?, but I don't know how to say: “For this vertice, the weight for this bone should be this number”
I think what I want to say is something like..
For each indice in “verts_in_group”,
Set Vertex Weights To:
CC_Base_Pelvis = 0.622
CC_Base_L_ThighTwist01 = 0.036
CC_Base_R_ThighTwist01 = 0.240
CC_Base_Waist = 0.062
Iterate until each vertice in the array has been set
I know I'm missing stuff here. I've only just started to learn scripting and I don't know where the weight information shown in this panel is stored. I'm assuming it's "in" the vertice since I had to click on a vertice to see it. I am looking on the API website too but it doesn't seem like they have examples there so it's difficult for a beginner to use.
Thanks much for any help
UPDATE:
Thank you for the links – I did see those before I asked: The first one has some great examples but they are all for “getting” vertices in a group, I already have the vertices I need to work on (as an array), and since I'm importing/working on the same mesh every day those will not change.
I think the last one shows how to iterate through vertices and see if they are assigned to a group and if so multiply the weight by a factor. I want to set them to specific weights by bone (like in the image), not increase all of their weights by a factor.
The middle two both go to the same place. It's more than 8 years old, but it worked, with a slight edit, to get some data back about one of my vertex groups:
import bpy
obj = bpy.context.object
def get_weights(ob, vgroup):
group_index = vgroup.index
for i, v in enumerate(ob.data.vertices):
for g in v.groups:
if g.group == group_index:
yield (i, g.weight)
break
import bpy
obj = bpy.context.object
vgroup = obj.vertex_groups[16] #I changed 0 to 16 to target a specific vertex group
# iterate over index, weights
for i, w in get_weights(obj, vgroup):
print(i, w)
The first column returned is all the indices for my group, but the second column shows only one weight, not all the weights associated with each vertice per each bone that affects it (like you see in the image at the top). Since at least four deform bones are affecting each of these vertices I would expect to see more data here – Maybe I'm thinking about this in the wrong way - Are the weights stored in the bones instead of the vertices?
551 1.0
556 1.0
662 1.0
664 1.0
698 1.0
2220 1.0
2230 1.0
2236 1.0
Final Summary: Wow - thank you so much for that answer. Your code worked for me and I think I understand most of the logic due to your detailed explanation and code comments:
the object has a mesh: (obj.data) the object's mesh has vertices: (obj.data.vertices) the vertices have groups (obj.data.vertices[x].groups) the groups have “vertex group elements” like indexes and weights (vge.group) (vge.weight)
Seems like one of the takeaways here is not to see the Vertex Group as a container of vertices, but rather as a property of a vertice (that's why you said “vertex groups don't know their vertices”) and it makes some sense since an object in the physical world would not be able to occupy two containers at the same time.
For any other beginner like myself: Even with the great explanation from Blunder I was stuck on this still because I only just now realized that something automatically makes vertex groups for bones and gives them the same names as the bones. So I thought the panel in my attached screen shot was showing me “weights per bone” when it was actually showing me “weights per group”. Once I realized that, I was better able to follow along with the code.