Working with mesh geometry, it may be necessary to assign each vertex some custom properties or data that must be written to the blend-file when saved, and which must be accessed later.
However, an attempt to assign the necessary data to the vertexes through the creation of custom properties fails. Instead of the custom vertex property, only a tuple with reference to the type of the property is created.
1 2 3 4 5 6 7 8 9 10 11 |
import bpy class PROP_cls(bpy.types.PropertyGroup): prop: bpy.props.IntProperty(default=1) bpy.utils.register_class(PROP_cls) bpy.types.MeshVertex.prop = bpy.props.PointerProperty(type=PROP_cls) bpy.context.object.data.vertices[0].prop # (<built-in function PointerProperty>, {'type': <class '__main__.PROP_cls'>}) |
This happens because we can set custom properties only to the ID-types objects, for example, meshes, bones, shaders. But vertexes do not correspond to this type, therefore it is impossible to give them additional properties in this way.
It seems that the problem cannot be solved … But we have BMesh, which provides more opportunities in terms of working with meshes!
It is also impossible to directly assign additional properties to vertexes through the BMesh structure. When updating mesh data from the BMesh structure, only the main data is saved. However, BMesh allows the user to specify additional data to vertices (as well as edges, polygons, and loops) through the layers system.
The vertex layer in BMesh is an array of a certain data type with a size equal to the number of vertices. Each cell of the array is tied to a specific vertex through its index i.e. the cell of the layer with index 0 is associated with the vertex with index 0, the cell with index 1 – with the vertex with index 1, etc.
Having created such a layer, we get an array of cells, into which we can write the custom data we need, each of which corresponds to its own vertex.
To create a vertex layer we need to execute the following code:
1 2 3 4 5 6 |
import bpy import bmesh obj_data = bpy.context.object.data bm = bmesh.from_edit_mesh(obj_data) vert_layer = bm.verts.layers.int.new('vert_layer') |
Here we created a vertex layer of type “int”, so we can specify for each vertex additional data of one integer type number.
Having the layer, we can enter the necessary data into it. For example, save the currently selected vertices:
1 2 3 4 5 6 |
for v in bm.verts: if v.select: v[vert_layer] = 1 else: v[vert_layer] = 0 bmesh.update_edit_mesh(obj_data) |
For selected vertices, 1 will be written to the layer, for non-selected vertices – 0.
As we can see, data from the vertex layer is accessed from the vertex itself using the layer name.
1 2 3 |
bm.verts[0]['vert_layer'] # 1 |
A layer itself can be obtained by its name through calling the get() method:
1 |
bm.verts.layers.int.get('vert_layer') |
The following code will print our custom data (selection status) from a previously created layer:
1 2 3 4 5 6 7 8 9 10 11 |
import bmesh import bpy obj = bpy.context.object bm = bmesh.from_edit_mesh(obj.data) vert_layer = bm.verts.layers.int.get('vert_layer') for v in bm.verts: print(v[vert_layer]) # 1 0 0 1 |
Hi, thanks for this amazing post!
I was wondering if there is a way to add a prop in a panel, so we can add or edit the values through the UI.
for example whenever I select a vertex, it shows me its custom property, and I can edit it whenever I want.
thanks in advance.
Hi!
Created vertex properties could be accessed through the object attributes. For example, for “vert_layer” from the article
bpy.context.object.data.attributes[‘vert_layer’].data
I just need to add a 2D integers array as a custom property instead of an integer. I imagine that the custom property will be accessible via Geometry Nodes.
Not shure that custom properties would be accessible from GN. Maybe to try to make the required attributes fields in Geometry Nodes.
Oh my gosh!! Build my own nodes… I know I saw it somewhere. Any pointers? Thanks anyway. (If you consider my purpose is to model nice dancer’s legs, I am a bit further that i thought I’d go).
To stady GN well you can start from the Erindale tutorials on youtube.
Now I have been testing the thing and: When I run the script that is supposed to give me an error I don’t and when I run the “good” one I get an error. I think that now (blender 3.0 ran on Windows 7, 64) vertices have an ID so we can give them a property. Question is how do I get it? .
No, vertices is still not ID objects.
PERrrrrfect. 1001 times thank you, just what I need.