Python set active face/batch unwrap Follow Active Quads 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



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
    bm.select_history.add(face)
    #Select linked geometry
    bpy.ops.mesh.select_linked(delimit={'SEAM'})
    #Unwrap using Follow Active Quads
    bpy.ops.uv.follow_active_quads()
    #Hide when done
    bpy.ops.mesh.hide(unselected=False)


My coding skills are admittedly weak at best, so if anyone has a better suggestion with or without scripting, please shoot
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
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_mode(type='FACE')
bpy.ops.mesh.select_all(action='DESELECT')
bm = bmesh.from_edit_mesh(obj.data)

for face in bm.faces:
    if not face.hide:
        face.select = True
        bm.faces.active = face
        bpy.ops.mesh.select_linked(delimit={'SEAM'})
        bpy.ops.uv.follow_active_quads(mode='EVEN')
        bpy.ops.mesh.hide(unselected=False)

bpy.ops.mesh.reveal()
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.uv.unwrap()
bpy.ops.object.mode_set(mode='OBJECT')
bm.free()