16
$\begingroup$

I've puzzled about this for a while, but haven't found an answer I understood. This snippet below does add geometry (3 verts and a face) but it also generates an error, Does going to object mode make the data reference in bm be cleared? if so, how does data.vertices still get updated?

ReferenceError: BMesh data of type BMesh has been removed
Error: Python script fail, look in the console for now...

any ideas, this is the cut down script ( run it with a cube in edit mode)

import bpy, bmesh

obj = bpy.context.object
bm = bmesh.from_edit_mesh(obj.data)

bm.verts.new((2.0, 2.0, 2.0))
bm.verts.new((-2.0, 2.0, 2.0))
bm.verts.new((-2.0, -2.0, 2.0))

set_of_verts = set(bm.verts[i] for i in range(-3,0))
bm.faces.new(set_of_verts)

bpy.ops.object.mode_set(mode='OBJECT')
bm.to_mesh(obj.data)  

I have a few scripts that might benefit using the BMesh module for adding geometry, I know how to do it in the pre BMesh way.

Edit, using answer: here's how to add tris and quads while staying in edit mode https://gist.github.com/zeffii/5668669

$\endgroup$
  • 2
    $\begingroup$ Instead of set_of_verts you could also use the return-value of the bm.verts.new(...) which is exactly the vertex you want. $\endgroup$ – WorldSEnder May 9 '14 at 19:14
  • $\begingroup$ you should make a proper answer then, show the neatest way. $\endgroup$ – zeffii May 9 '14 at 21:47
  • $\begingroup$ Alternatively, if you want to keep your current approach, you can replace it by the simpler bm.verts[-3:]. $\endgroup$ – CoDEmanX May 10 '14 at 23:33
16
$\begingroup$

The issue with this script is when you exit editmode, the editmesh you were editing becomes invalid (thats good, but not what you want).

So instead, just exit editmode and blender will handle converting the modified bmesh into the object mode mesh data.

import bpy, bmesh

obj = bpy.context.object
me = obj.data
bm = bmesh.from_edit_mesh(me)

v1 = bm.verts.new((2.0, 2.0, 2.0))
v2 = bm.verts.new((-2.0, 2.0, 2.0))
v3 = bm.verts.new((-2.0, -2.0, 2.0))

bm.faces.new((v1, v2, v3))

bmesh.update_edit_mesh(obj.data)

# This is optional, you could also stay in editmode.
bpy.ops.object.mode_set(mode='OBJECT')

Note, if you want to stay in editmode, call bmesh.update_edit_mesh(me) at the end of the script to ensure ngons are re-triangulated for display.

$\endgroup$
  • $\begingroup$ OP can also see blender.org/documentation/blender_python_api_2_69_release/… for more details $\endgroup$ – iKlsR May 28 '13 at 13:54
  • 2
    $\begingroup$ Thanks @ideasman42 : bmesh.update_edit_mesh(obj.data) directly fixes my problem. This wasn't clear from docs, which in this case I didn't find very useful (even the current docs). $\endgroup$ – zeffii May 28 '13 at 14:36
3
$\begingroup$

The issue is clearly the one already mentioned in other answer(s): the editmesh becomes invalid when you exit editmode. But there is a "simplification" for your script.

Note: Every variable t_* will become invalid once you exit editmode

So here is the simplified script:

import bpy, bmesh

obj = bpy.context.object
me = obj.data
t_bm = bmesh.from_edit_mesh(me)

t_v1 = t_bm.verts.new((2.0, 2.0, 2.0)) # the created vertex
t_v2 = t_bm.verts.new((-2.0, 2.0, 2.0))
t_v3 = t_bm.verts.new((-2.0, -2.0, 2.0))

t_face = t_bm.faces.new([t_v1, t_v2, t_v3]) # .new() always returns the produced (bmesh-)object
# Saving the vertices/edges/faces for backreference.

# Once you run this command you cannot access the bmesh anymore
bpy.ops.object.mode_set(mode='OBJECT')

Almost every .new() on any list will return the newly added data.

$\endgroup$

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.