2
$\begingroup$

I am fairly new to python scripting in Blender. I am creating a tool for my workflow and can't seem to figure out several elements, although I do know how to do them in other languages.

I can get the index numbers of the faces in an object. How would I store faces selected in a variable or array that can be accessed after edit mode is exited?

$\endgroup$
2
  • $\begingroup$ You might want to consider using a data layer approach. Saving face indexes in a list for example could provide misleading results when faces are added / removed during an edit. $\endgroup$ – batFINGER Dec 21 '16 at 10:34
  • $\begingroup$ Can you please demonstrate a data layer approach. I have tried to use global variables to store the index of a face to be accessible by other functions, but that doesn't seem to work. Basically, I'm trying to select faces, store them in a variable, so that if I close Blender and reopen it, I can perform an operation on those faces regardless of what additional faces are selected/ not selected on a mesh. Is that possible? $\endgroup$ – ACopeLan Jan 6 '17 at 17:44
1
$\begingroup$

Storing custom data on a face

Example adds an int layer, named "Selection" to the context object mesh (in edit mode) and assigns each faces corresponding layer value to 1 if selected else 0.

This data is stored "on" the face, it will be lost if the face is deleted, but will remain the same if the face indices are re-sorted.

import bpy
import bmesh

context = bpy.context
obj = context.edit_object
mesh = obj.data

bm = bmesh.from_edit_mesh(mesh)

# custom int property on face
selectionlayer = bm.faces.layers.int.get("Selection")
if not selectionlayer:  # create one
    selectionlayer = bm.faces.layers.int.new("Selection")

# assign 1 if face selected else 0
for f in bm.faces:
    f[selectionlayer] = int(f.select)

bmesh.update_edit_mesh(mesh)
mesh.update()

Save and close, reopen and run, and there will still be an int prop assoc with each face that will match the selection when above was run.

import bpy
import bmesh

context = bpy.context
obj = context.object
mesh = obj.data

bm = bmesh.new()
bm.from_mesh(mesh)

# get the custom layer
customlayer = bm.faces.layers.int.get("Selection")
if customlayer:  # create one
    # print face index, layer value 
    for f in bm.faces:
        print("face %d " % f.index, f[customlayer])
$\endgroup$
5
  • $\begingroup$ Oh wow. I'll have to study that for a bit. So "Selection" is a variable that is initialized as it is assigned to the variable "selectionlayer"? $\endgroup$ – ACopeLan Jan 10 '17 at 20:48
  • $\begingroup$ How are you assigning 1 if a face/ faces are selected? Is it it the array data from f.select? Are you saying it's true if any faces are selected, or is 1 an actual property? Lastly, are you saying that anything that is entered into the data layer "Selection" is automatically stored for global use? $\endgroup$ – ACopeLan Jan 10 '17 at 20:58
  • $\begingroup$ The code under the comment # assign 1 if face selected else 0 If the face is selected then the data layer prop for that face is set to 1, 0 otherwise. It is storing the layer data on the mesh, and is saved to that mesh with bm.to_mesh or bmesh.updata_edit_mesh. The second script shows that the selection is saved. $\endgroup$ – batFINGER Jan 11 '17 at 7:12
  • $\begingroup$ VERY nice batFINGER. Are you using int(f.select) as a strong type instead of using f.select? $\endgroup$ – ACopeLan Jan 11 '17 at 20:25
  • $\begingroup$ Just wanted to emphasize it's an int layer as there is no bool layer. 1 if f.select else 0 could be another way. Doesn't matter too much, as python is very forgiving on type. $\endgroup$ – batFINGER Jan 14 '17 at 11:46
1
$\begingroup$

If you store the list of indices in a list object (array), it will be accessible even after the object is no longer in edit mode.

import bpy, bmesh

o = bpy.context.object

# Create bmesh object. This particular method requires that the object will be in edit mode.
bm = bmesh.from_edit_mesh( o.data )

# Store list of selected face indices in object (will be empty if not face is selected)
selected_faces_list = [ f.index for f in bm.faces if f.select ]

# Go to object mode
bpy.ops.object.mode_set( mode = 'OBJECT' )

# Print content of list to show that it still contains face indices although we are now in object mode
print( selected_faces_list )
$\endgroup$
2
  • $\begingroup$ Thanks! But I guess I should add more clarity to the question. How do I store a selected face index (or several) in a global variable or an array so that I can access that index after it is no longer selected visibly? Kind of like how materials work, where after assigning a material, you can make changes to those specific faces- though they are not selected visibly. $\endgroup$ – ACopeLan Dec 21 '16 at 16:33
  • $\begingroup$ So you want to use this data by a piece of code that will run at a separate time and not immediately after you've selected the faces? If so, see this page for examples how you create your own globally accessed property group: blender.org/api/blender_python_api_2_65_release/… $\endgroup$ – TLousky Dec 21 '16 at 17:26

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.