Selecting a face through the API

I am beginer on Blender, and Python.
After running the following script:



import bpy
    
# retrieve the active object
bpy.ops.object.mode_set(mode = 'OBJECT')
obj = bpy.context.active_object

# retrieve the active face
i = obj.data.faces.active
        
# deselect everything
bpy.ops.object.mode_set(mode = 'EDIT') 
bpy.ops.mesh.select_all(action = 'DESELECT')

# reselect the originally selected face
obj.data.faces[i].select = True


I would expect to see in the 3D view, in EDIT mode, the originally selected face of the active object still selected.

This is not the case, everything is deselected.

Can somebody explain to me where my reasoning is wrong ?

The mesh object in python reflects the state of the mesh as it was, the last time it was in object-mode. So if you wish to make a face selection (not using operators, as they work in edit-mode), you first have to enter object-mode.

import bpy

# retrieve the active object
bpy.ops.object.mode_set(mode = 'OBJECT')
obj = bpy.context.active_object

# retrieve the active face
i = obj.data.faces.active

# deselect everything
bpy.ops.object.mode_set(mode = 'EDIT')
bpy.ops.mesh.select_all(action = 'DESELECT')

# reselect the originally selected face
bpy.ops.object.mode_set(mode = 'OBJECT')
obj.data.faces[i].select = True
bpy.ops.object.mode_set(mode = 'EDIT')

What this does is that after deselecting everything, the mode is changed to object-mode. This updates the mesh-data python accesses. So then you can select the face and re-enter edit-mode again.
This can be confusing, but usually when things don’t work like expected, you’re in the wrong mode.

Thank you Crouch

I think I caught your point.

However, even with your corrected code, it still doesn’t work.
Everything is still deselected at the end in the 3D view.
I would expect to see THE face “illuminated” Everything is black.

Thank you again for your time.

The python API reflects how Blender handles things internally and that face.select flag simply represents the state of the face itself.
Simply put, in order to actually select the face you have to select all corners of the face.

The following code is taken from my AddGo add-on*:


vert_list = [vert for vert in mesh.vertices]
for vert in face.vertices:
    vert_list[vert].select = True
    face.select = True

Hope this helps.

Sorry Crouch, your code works in the normal case
(which here means when the “Face select mode” button in the 3D View header is depressed).

This is only when the “Edge select mode” button is depressed that the face.select = True code doesn’t seem to do its job.
I am not experienced enough to say if this is logical behaviour or not.

Same for your code Vekoon (may be more robust ?)

Anyway a lot of thanks to both of you.

You are correct, my code only works in vertex select mode. I found a way out of it, although it’s a bit more complicated that it should be really, but here it goes.


bpy.ops.object.mode_set(mode='EDIT', toggle=False)
sel_mode = context.tool_settings.mesh_select_mode
context.tool_settings.mesh_select_mode = [True, False, False]
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)

mesh = ob.data

vert_list = [vert for vert in mesh.vertices]
for vert in face.vertices:
    vert_list[vert].select = True
face.select = True
    
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
context.tool_settings.mesh_select_mode = sel_mode
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)

1 Like

Super, vekoon !

Your idea to save the select mode to restaure it at the end works perfectly.

Thanks to both of you again.