19

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

zeffii
  • 39,634
  • 9
  • 103
  • 186

2 Answers2

20

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.

ideasman42
  • 47,387
  • 10
  • 141
  • 223
  • OP can also see http://www.blender.org/documentation/blender_python_api_2_69_release/info_gotcha.html#edit-mode-memory-access for more details – iKlsR May 28 '13 at 13:54
  • 2
    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). – zeffii May 28 '13 at 14:36
3

The issue is clearly the one already mentioned in other answers, the editmesh becomes invalid when you exit Edit Mode. But there is a "simplification" for your script.

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

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.

Duarte Farrajota Ramos
  • 59,425
  • 39
  • 130
  • 187
WorldSEnder
  • 1,616
  • 1
  • 15
  • 37