Note that vertex groups will not be dumped: vertex groups are not part of a mesh but of an object. (yes, if you didn't know that already, you can have more than one object pointing to the same mesh data, each with its own vertex groups)
This is done by code that is a lot more Pythonic (whatever that means, for me pragmatism is more important than style, as long as it is readable and documented). It uses a lot of introspection to keep the code short and sweet as well. Of course it helps that Blender attribute layers (aka CustomData) is very flexible and well designed (well,... mostly, see Bugs below)
Functionally the add-on hasn't changed much: the interface is cleaner (no more separate selection of what will be dumped, you either choose just geometry or everything), and now all objects that are selected are dumped. This might give a slightly faster workflow.
AvailabilityThe updated code for DumpMesh and CreateMesh can be found on my GitHub repository. DumpMesh can be downloaded directly from this link, as can CreateMesh if your are interested to look at the code.
BugsBlenders Python API is generally well designed and adequately documented but there are still some bugs and strange design issues:
- not documented at all but it is used by the skin modifier. And the
bm.verts.layers.skinlayer the skin modifier creates has a name that is an empty string
- has a documentation entry but is marked as todo. Fair enough, because this might be for Ptex stuff that is sort of shelved for now. In the add-on it is mostly ignored.
- If you add vertices, edges or faces to a bmesh you must ensure that the sequences they are members of can be indexed. You can do this with
bm.verts.ensure_lookup_table()or equivalent. If you not only need to be able to do
bm.verts[i]but need the actual index as well, like
bm.verts[i].indexyou need to call
bm.verts.index_update()otherwise all indices are -1. So far so good, however for loops this appears to be either unfinished or I don't understand it: there is no
ensure_lookup_table()for loops, apparently this is taken care of by the faces, but any index attribute of a BMLoop is -1. now
bm.faces[i].loopsdoes have an
index_update()but it will generate only indices for the loops of that particular face and will start at 0. However when transfering a bmesh to a regular mesh the indices of all loops in the whole mesh are properly initialized, so there is apparently hidden functionality to take care of this. Of course most of the time you can do without but in the addon I dump loop layers as dictionaries of dictionaries that can be indexed as d[faceindex][loopindex] where loopindex is initialy derived from the complete mesh and therefore numbered as one unbroken sequence of all the loops.
- factories instead of instantiation from a class
- BMesh, BMVert, BMSinVert, etc. are not fully fledged classes. You cannot subclass them and you cannot instantiate them with
BMesh(). also most have no
__repr__()function and also cannot be pickled. This means that especially for layer attributes like BMSkinVert with more than one attribute you have to know what to assign to which attribute, which is cumbersome. introspection is no help here because you cannot know which attribute is to be saved and which one is just for temporary use.