14
$\begingroup$

If I select a face of a cube and switch over to the internal Python console and pass:

bpy.context.selected_objects

I get:

[bpy.data.objects['Cube']]

instead of something like [bpy.data.objects['Cube'].f[1]].

Coming from Maya I was looking for something like:

import pymel.core as pc

print pc.ls(sl=True)

which in the above case would return the face id.

Same thing applies for vertices and edges.

How can I go about getting a detailed selection list programmatically?

$\endgroup$

3 Answers 3

6
$\begingroup$

You may be interested into bmesh module's select_history

import bpy
import bmesh

me = bpy.context.object.data

bm = bmesh.from_edit_mesh(me)

for elem in bm.select_history:
    print(repr(elem))

# Variant 1 - get the active edge
try:
    active_edge = filter(lambda elem: isinstance(elem, bmesh.types.BMEdge), 
        reversed(bm.select_history)).__next__()
except StopIteration:
    active_edge = None


# Variant 2 - same, but less geeky ;)

for elem in reversed(bm.select_history):
    if isinstance(elem, bmesh.types.BMEdge):
        active_edge = elem
        break
else:
    active_edge = None


# Get selected faces in order

for elem in bm.select_history:
    if isinstance(elem, bmesh.types.BMFace):
        print(repr(elem))


# Get all selected faces
# Note: bm.select_history lacks geometry selected via border select, lasso, etc.
#       (mass-selection operators)!

for face in bm.faces:
    if face.select:
        print(repr(face))
$\endgroup$
4
$\begingroup$

PyMEL's ls seems to roll several related functions into one (match by type, name, regexp-pattern, etc.). There's no such function built in to Blender's Python API, so you must create selection list manually.

You have to know what element you need to process. If it's a list of MeshVertex, MeshEdge or MeshPolygon, filter out objects whose type isn't "MESH". It's also possible that edit-mode and object-mode data isn't synced, which will happen if the script is run when the object is in edit-mode (presumably while the user's selecting elements). To make the correct selection list regardless of the object's state, run update_from_editmode beforehand. Then you can create the list:

import bpy

obj = bpy.context.object
mesh = obj.data # Assumed that obj.type == 'MESH'
obj.update_from_editmode() # Loads edit-mode data into object data

selected_polygons = [p for p in mesh.polygons if p.select]
selected_edges = [e for e in mesh.vertices if e.select]
selected_vertices = [v for v in mesh.vertices if v.select]

# ... process selection list...

This also applies to the newer mesh editing API bmesh and also other object types (check the API doc's index if the element needed has a select* attribute), though can be a bit more involving for some types. For example, a curve object can contain more than one spline, so iteration over each splines must be chained in some way to reach all BezierSplinePoint:

import bpy
from itertools import chain

obj = bpy.context.object
curve = obj.data # Assumed that obj.type == 'CURVE'
obj.update_from_editmode() # Loads edit-mode data into object data

selected_cpoints = [p for p in chain(*[s.bezier_points for s in curve.splines])
                    if p.select_control_point]

# ... process selection list...
$\endgroup$
3
$\begingroup$

In blender there is a difference between an object and elements such as faces, edges, and vertices.

I don't know if a collection of selected elements is stored anywhere, but you can iterate through every face and check if it's selected via polygon.select:

import bpy

ob = bpy.data.objects['Cube']

for poly in ob.data.polygons:
    if poly.select == True:
        # Do stuff

Note that you must be in object mode for this to work.

$\endgroup$

You must log in to answer this question.

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