0
$\begingroup$

I am brand new to Python, and cobbling things together from various sources, so I have next to NO idea what works, what doesn't work, or WHY things work.

I'm creating a script to apply a mirror modifier, then split the object into its two sides. I'm using two slightly different routines depending on whether it is one symmetrical object with a center line, or two mirrored objects with no connected geometry.

When I used this code, it worked:

mesh = ob.data
bm=bmesh.from_edit_mesh(mesh)

bpy.ops.mesh.select_mode(type='VERT')
vtest = False  ##see if we can select side of active
for vert in bm.verts:
    if(vert.co[0] == 0):
      vert.select = True
      bm.select_history.add(vert)
      vtest = True
      break


if(vtest):  ## select side of active and part
    bpy.ops.mesh.select_axis(sign='NEG')
    bpy.ops.mesh.select_mode(type='FACE')
    bpy.ops.mesh.separate(type='SELECTED')

However, if I selected the vertices in a loop and tried to switch to face mode it dropped the selection.

  else:     
        for vert in bm.verts:
            if(vert.co[0] <0):
                vert.select = True

        bpy.ops.mesh.select_mode(type='FACE')
        bpy.ops.mesh.separate(type='SELECTED')

This threw the error 'no selection.' and if I stopped the script just before the FACE selection mode switch, the mesh was in edit mode, all the vertices on the left side were selected, and if I then clicked face select mode, everything would be deselected.

I can't explain that.

The code that I finally got to work is BS and i'd like to know what fifty things I did wrong.

bm.select_mode = { 'FACE' }
bmesh.update_edit_mesh(ob.data)
bpy.ops.object.mode_set(mode = 'OBJECT', toggle = False)
bpy.ops.object.mode_set(mode = 'EDIT', toggle = False)
bpy.ops.mesh.select_mode(type='FACE')

If I leave out any of those lines, it fails.

My BASE question is: why can I select vertices using the 'select side of active' command, then swap into face mode and convert the selection to faces but if I select the vertices myself in a loop and switch, it drops them?

$\endgroup$

2 Answers 2

4
$\begingroup$

Flush the selection

The bmesh module has some methods for flushing selection.

Selection / Flushing

As mentioned above, it is possible to create an invalid selection state (by selecting a state and then de-selecting one of its vertices’s for example), mostly the best way to solve this is to flush the selection after performing a series of edits. this validates the selection state.

Test Script: run in edit mode, selects vertices with

import bpy
import bmesh


context = bpy.context
ob = context.edit_object
me = ob.data

bm = bmesh.from_edit_mesh(me)
for v in bm.verts:
    v.select_set(v.co.z < 0)

bm.select_mode = {'VERT', 'EDGE', 'FACE'}
bm.select_flush_mode()
#bm.select_flush(True) # or select flush, deselect all first. 
# put in tool in face select mode (without op)    
context.tool_settings.mesh_select_mode = (False, False, True)
#bpy.ops.mesh.separate(type='SELECTED')

After the flush above only faces with all vertices selected are selected. Verts not part of a selected face are deselected.

$\endgroup$
2
  • $\begingroup$ it works great, but i don't understand why; if you'd care to comment. does "flush the selection" mean "deselect everything"? or does it mean something else, like some kind of reset? 'flush vertices, because we're going to select faces'? 'flush vertices that aren't on selected edges, and flush edges that aren't on selected faces'? $\endgroup$
    – blr
    May 2, 2020 at 19:20
  • $\begingroup$ As mentioned in quote from docs it validates the selection. If you select a face then all its edges and vertices are selected. Going "up" doesn't imply same. ie select all verts doesn't automatically select faces and edges. $\endgroup$
    – batFINGER
    May 2, 2020 at 19:44
1
$\begingroup$

Face and vertex selection is different, because you can select only part of vertices belonging to a single face. Conversion is needed between these selections and is done automatically when you switch selection modes using the UI so if you use operators to switch selection modes, they sort things out automatically. You can do just that what you are doing - switch selection modes with operators, or you could just select all the faces that have all their vertices selected with Python as well. It could look something like:

import bpy

data = bpy.context.object.data

for f in data.polygons:
    s = True
    for v in f.vertices:
        if not data.vertices[v].select:
            s = False
    f.select = s

There might be a more efficient way to do this that I am not aware of but this works.

$\endgroup$
0

You must log in to answer this question.

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