# Python BMESH: For loop breaking trying to split mesh via UV Islands

Perhaps I am not using bmesh properly. I'm trying to create a script that splits a mesh by it's UV islands.

The script attempts to iterate through each face of mesh and...

1. select a face.
2. select linked faces via uv island
3. Toggle Scene.tool_settings.use_uv_select_sync #so can split
4. split selected faces.

Here is the code (it's part of a larger script)

import bpy
import bmesh

bpy.ops.object.mode_set(mode = 'EDIT')
ob = bpy.context.object
bm = bmesh.from_edit_mesh(ob.data)

for face in bm.faces:
bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='FACE')
bpy.context.scene.tool_settings.use_uv_select_sync = True
face.select = True
bpy.context.scene.tool_settings.use_uv_select_sync = False
bpy.ops.mesh.split()
bpy.ops.mesh.select_all(action='DESELECT')

ob.data.update()
bpy.ops.object.mode_set(mode = 'OBJECT')
#return {'FINISHED'}


The code seems to work for the first UV island, then it just stops. I'm not sure how to troubleshoot. Any help be greatly appreciated.

• Probably because once the first iteration is done, bm.faces is updated, so it is no more iterable. – lemon Feb 14 '17 at 14:19
• Makes sense. I figured it was stopping as soon as the split happened. – admbro Feb 14 '17 at 19:21
• so... my first thought is a while trueFalse loop. Then obtain bm (inside the loop) get the first face, get the selection, verify if the selection = all (then trueFalse becomes false), then if not false apply the split and update the ob. But all that is not tested. – lemon Feb 14 '17 at 19:26

## EDITED:

@batFINGER wrote a more robust solution to this issue, as can be seen in this answer.

Solved this by splitting the process into two parts: the first finds faces in each UV island, and the 2nd performs the actual split. Also, you used the wrong operator (bpy.ops.uv.select_linked_pick) which was part of the original problem (should have used bpy.ops.uv.select_linked).

import bpy, bmesh
context = bpy.context

ob = context.object
me = ob.data
scene = context.scene

bpy.ops.object.mode_set(mode = 'EDIT')
bm = bmesh.from_edit_mesh(me)
bm.select_mode = {'FACE'}
faceGroups = []
#bm.faces.ensure_lookup_table()

bpy.ops.mesh.select_mode(use_extend=False, use_expand=False, type='FACE')
save_sync = scene.tool_settings.use_uv_select_sync
scene.tool_settings.use_uv_select_sync = True
faces = set(bm.faces[:])
while faces:
bpy.ops.mesh.select_all(action='DESELECT')
face = faces.pop()
face.select = True
selected_faces = {f for f in faces if f.select}
selected_faces.add(face) # this or bm.faces above?
faceGroups.append(selected_faces)
faces -= selected_faces

scene.tool_settings.use_uv_select_sync = save_sync

for g in faceGroups:
bpy.ops.mesh.select_all(action='DESELECT')
for f in g:
f.select = True
bpy.ops.mesh.split()

ob.data.update()
bpy.ops.object.mode_set(mode='OBJECT')

• Perfect! Learned a lot from your approach. Thank you so much for your help. :) – admbro Feb 15 '17 at 18:11
• @batFINGER, you've found a real elegant solution, well done! – TLousky Oct 14 '17 at 7:50
• @batFINGER did you test this code? I used indices rather than direct face references earlier assuming that once you perform a mesh.split() it will essentially rewrite the mesh structure and kill the bmesh object. – TLousky Oct 14 '17 at 21:03
• @TLousky Either way i think. Doesn't kill the bmesh in my tests, and the indices don't get mixed up. Was prob a one face case or something in original logic that gave weird results for the splattercake of uv islands that a "smart" project does on Suzanne. While and pop saves all that this in that testing code. – batFINGER Oct 21 '17 at 13:05
import bpy, bmesh
obj = bpy.context.object
me = obj.data

bpy.ops.object.mode_set(mode = 'EDIT')
bm = bmesh.from_edit_mesh(me)

edges=[]
for e in bm.edges:
if e.seam:
edges.append(e) #get seam marked edges

bmesh.ops.split_edges(bm, edges=edges)

bmesh.update_edit_mesh(me, False)