TL;DR: How do I set a bmesh face as active through Python?

Long Version: I got this random pre-made complex mesh of a tree, it is well modeled, but it came with garbled UV coordinates, without properly unwrapping it, it is pretty much useless.

Manually unwrapping seems out of the question (too many hundred leaves). They are all quad based though, so I started trying to create a very basic script to loop through visible faces > select all linked > unwrap it using Follow Active Quads.

If it helps this is the average leaf appearance

enter image description here

It works for the most part for single selections, however I always get RuntimeError: Error: No active face is not selected, when I try to loop over all faces.

According to this answer adding it to selection history should do the trick and set a vertex (face also?) as active, but it is not working for me.

This is what I cobbled up copy pasting from here and there.

import bpy
import bmesh

# Get the active object
obj = bpy.context.object
# Get the active mesh
me = bpy.context.object.data

#get bmesh (Object needs to be in Edit mode)
bm = bmesh.from_edit_mesh(me)
faces = bm.faces[:]

for face in faces:
    #Select a face
    #Select linked geometry
    #Unwrap using Follow Active Quads
    #Hide when done

My coding skills are admittedly weak at best, so if anyone has a better suggestion with or without scripting, please shoot

  • 1
    $\begingroup$ I don't know why, but first thing I have think of reading this question was this: blender.stackexchange.com/questions/72011/… $\endgroup$
    – cgslav
    Jun 14 '17 at 23:31
  • $\begingroup$ That is indeed remarkably similar to what I am trying to achieve in terms of UV result, yes. It is probably a bit simpler though, because all tree leaves are basically a quad strip. consisting about 1 to 4 quads. I was trying to find a simple way of marking start and end points on all leaves, but can't seem to manage it easily. $\endgroup$ Jun 14 '17 at 23:47
  • 1
    $\begingroup$ You can change the active bmesh face with bm.faces.active = face, you can select a specific face with face.select = True but I doubt that is going to help a great deal. You can manuallly select all and unwrap following active quad, then use Pack Islands in the uv editor to spread them out. $\endgroup$
    – sambler
    Jun 15 '17 at 8:52

You can set the active face in your loop with bm.faces.active = face.

With what you have so far, you are looping through every face and doing select linked, even if you may have already unwrapped and hidden the face.

The following script seems to do what you are trying to accomplish.

import bpy
import bmesh

obj = bpy.context.object
bm = bmesh.from_edit_mesh(obj.data)

for face in bm.faces:
    if not face.hide:
        face.select = True
        bm.faces.active = face

  • $\begingroup$ Ah yes excellent that is exactly what I was aiming for. That was another point I meant to fix, but my skills got in my way. As it stands mine is pretty dumb, brute-force looping over every face more than once, but I had not figured out how to filter out hidden faces. Many many thanks, will give it a try later today as soon as I'm back at the computer but looks very promising. $\endgroup$ Jun 15 '17 at 11:54
  • $\begingroup$ Alright, just tested it, takes quite a while to run on my complete mesh (which is totally expected) but works like a charm. Just made a few tweaks for my taste, like removing bpy.ops.uv.unwrap() at the end since I want all islands to totally fit the bounds so they completely cover the potential leaf texture. Again many thanks $\endgroup$ Jun 15 '17 at 16:20

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.