2
$\begingroup$

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.ops.uv.select_linked_pick(extend=False)
    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.

$\endgroup$
3
  • 2
    $\begingroup$ Probably because once the first iteration is done, bm.faces is updated, so it is no more iterable. $\endgroup$
    – lemon
    Commented Feb 14, 2017 at 14:19
  • $\begingroup$ Makes sense. I figured it was stopping as soon as the split happened. $\endgroup$
    – admbro
    Commented Feb 14, 2017 at 19:21
  • 1
    $\begingroup$ 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. $\endgroup$
    – lemon
    Commented Feb 14, 2017 at 19:26

2 Answers 2

3
$\begingroup$

EDITED:

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

ORIGINAL 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).

enter image description here

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
    bpy.ops.uv.select_linked()
    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')
$\endgroup$
4
  • 1
    $\begingroup$ Perfect! Learned a lot from your approach. Thank you so much for your help. :) $\endgroup$
    – admbro
    Commented Feb 15, 2017 at 18:11
  • $\begingroup$ @batFINGER, you've found a real elegant solution, well done! $\endgroup$
    – TLousky
    Commented Oct 14, 2017 at 7:50
  • $\begingroup$ @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. $\endgroup$
    – TLousky
    Commented Oct 14, 2017 at 21:03
  • 1
    $\begingroup$ @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. $\endgroup$
    – batFINGER
    Commented Oct 21, 2017 at 13:05
1
$\begingroup$
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)

$\endgroup$

You must log in to answer this question.

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