19
$\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$
3
  • 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$ Commented May 9, 2014 at 19:14
  • $\begingroup$ you should make a proper answer then, show the neatest way. $\endgroup$
    – zeffii
    Commented May 9, 2014 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
    Commented May 10, 2014 at 23:33

2 Answers 2

20
$\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$
2
  • $\begingroup$ OP can also see blender.org/documentation/blender_python_api_2_69_release/… for more details $\endgroup$
    – iKlsR
    Commented May 28, 2013 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
    Commented May 28, 2013 at 14:36
3
$\begingroup$

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.

$\endgroup$
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .