Is there any API or method to get lists of UV island from Python script?
It seems there is no API to get lists of UV island in bpy module.
Thanks.
Blender Stack Exchange is a question and answer site for people who use Blender to create 3D graphics, animations, or games. It only takes a minute to sign up.
Sign up to join this communityThe API doesn't provide an operator or a data structure that specifies the list of UV islands as far as I know, but you can use the bpy.ops.uv.select_linked
operator as a basis for a script that finds all the islands.
import bpy
C = bpy.context
o = bpy.data.objects[ C.object.name ]
# Go to object mode to read UV data
bpy.ops.object.mode_set( mode = 'OBJECT' )
uvLayer = o.data.uv_layers.active
uvs = [ uvLayer.data[i] for i in range( len( uvLayer.data ) ) ]
others = uvs.copy()
islands = []
def select_island( uv ):
uv.select = True
bpy.ops.object.mode_set( mode = 'EDIT' )
bpy.ops.uv.select_linked()
bpy.ops.object.mode_set( mode = 'OBJECT' )
return [ i for i, uv in enumerate( uvs ) if uv.select ]
for i in range( len( uvs ) ):
bpy.ops.object.mode_set( mode = 'EDIT' )
bpy.ops.uv.select_all( action = 'DESELECT' )
bpy.ops.object.mode_set( mode = 'OBJECT' )
flat = [ idx for isle in islands for idx in isle ]
if i in flat: continue
island = select_island( uvs[i] )
exists = len( set( flat ).intersection( set( island ) ) )
if island and not exists: islands.append( island )
print( islands )
print( " number of islands: ", len( islands ) )
bpy.ops.uv
operators are not available (out of context) in object mode. This creates a weird situation can elicit an update gap that requires mode switching to overcome.
$\endgroup$
In Blender 2.92 API I have found such a function:
import bpy_extras
islands = bpy_extras.mesh_utils.mesh_linked_uv_islands(bpy.context.active_object.data)
But it works only in ObjectMode at the moment. In EditMode it creates an Exception. I hope it will be fixed in future versions.
But I found one issue with this method and here is my modification to fix it: https://devtalk.blender.org/t/python-improve-uv-shells-determination-mesh-linked-uv-islands/18063 https://pastebin.com/bpChLcSC
I solved this problem in reference to add-on UV Align\Distribute.
import bpy
import bmesh
__face_to_verts = defaultdict(set)
__vert_to_faces = defaultdict(set)
obj = bpy.context.active_object
bm = bmesh.from_edit_mesh(obj.data)
uv_layer = bm.loops.layers.uv.verify()
selected_faces = [f for f in bm.faces if f.select]
for f in selected_faces:
for l in f.loops:
id = l[uv_layer].uv.to_tuple(5), l.vert.index
self.__face_to_verts[f.index].add(id)
self.__vert_to_faces[id].add(f.index)
uv_island_lists = self.__get_island(bm)
def __parse_island(self, bm, face_idx, faces_left, island):
if face_idx in faces_left:
faces_left.remove(face_idx)
island.append({'face': bm.faces[face_idx]})
for v in self.__face_to_verts[face_idx]:
connected_faces = self.__vert_to_faces[v]
if connected_faces:
for cf in connected_faces:
self.__parse_island(bm, cf, faces_left, island)
def __get_island(self, bm):
uv_island_lists = []
faces_left = set(self.__face_to_verts.keys())
while len(faces_left) > 0:
current_island = []
face_idx = list(faces_left)[0]
self.__parse_island(bm, face_idx, faces_left, current_island)
uv_island_lists.append(current_island)
return uv_island_lists
It's very fast algorithm.
So, I fulfilled my requirement by this code.
https://github.com/nutti/Magic-UV/blob/develop/uv_magic_uv/muv_packuv_ops.py
Thanks to original author.