[Bf-extensions-cvs] [8db46434] master: Magic UV: Release v6.3

nutti noreply at git.blender.org
Mon Aug 10 09:24:43 CEST 2020


Commit: 8db46434a4b25569372a7172f83733ec14dffb31
Author: nutti
Date:   Mon Aug 10 16:07:26 2020 +0900
Branches: master
https://developer.blender.org/rBA8db46434a4b25569372a7172f83733ec14dffb31

Magic UV: Release v6.3

Added features
  - Clip UV

Updated features
  - World Scale UV
    * Add option "Area Calculation Method"
    * Add option "Only Selected"
  - UVW
    * Support multiple objects
  - Select UV
    * Support multiple objects
  - UV Inspection
    * Add Paint UV Island feature
    * Support multiple objects

Other updates
  - Fix bugs
  - Optimization

===================================================================

M	magic_uv/__init__.py
M	magic_uv/common.py
M	magic_uv/lib/__init__.py
M	magic_uv/op/__init__.py
M	magic_uv/op/align_uv.py
M	magic_uv/op/align_uv_cursor.py
A	magic_uv/op/clip_uv.py
M	magic_uv/op/copy_paste_uv.py
M	magic_uv/op/copy_paste_uv_object.py
M	magic_uv/op/copy_paste_uv_uvedit.py
M	magic_uv/op/flip_rotate_uv.py
M	magic_uv/op/mirror_uv.py
M	magic_uv/op/move_uv.py
M	magic_uv/op/pack_uv.py
M	magic_uv/op/preserve_uv_aspect.py
M	magic_uv/op/select_uv.py
M	magic_uv/op/smooth_uv.py
M	magic_uv/op/texture_lock.py
M	magic_uv/op/texture_projection.py
M	magic_uv/op/texture_wrap.py
M	magic_uv/op/transfer_uv.py
M	magic_uv/op/unwrap_constraint.py
M	magic_uv/op/uv_bounding_box.py
M	magic_uv/op/uv_inspection.py
M	magic_uv/op/uv_sculpt.py
M	magic_uv/op/uvw.py
M	magic_uv/op/world_scale_uv.py
M	magic_uv/preferences.py
M	magic_uv/properites.py
M	magic_uv/ui/IMAGE_MT_uvs.py
M	magic_uv/ui/VIEW3D_MT_object.py
M	magic_uv/ui/VIEW3D_MT_uv_map.py
M	magic_uv/ui/__init__.py
M	magic_uv/ui/uvedit_copy_paste_uv.py
M	magic_uv/ui/uvedit_editor_enhancement.py
M	magic_uv/ui/uvedit_uv_manipulation.py
M	magic_uv/ui/view3d_copy_paste_uv_editmode.py
M	magic_uv/ui/view3d_copy_paste_uv_objectmode.py
M	magic_uv/ui/view3d_uv_manipulation.py
M	magic_uv/ui/view3d_uv_mapping.py
M	magic_uv/updater.py
M	magic_uv/utils/__init__.py
M	magic_uv/utils/addon_updater.py
M	magic_uv/utils/bl_class_registry.py
M	magic_uv/utils/compatibility.py
M	magic_uv/utils/property_class_registry.py

===================================================================

diff --git a/magic_uv/__init__.py b/magic_uv/__init__.py
index 8630038a..b92714fe 100644
--- a/magic_uv/__init__.py
+++ b/magic_uv/__init__.py
@@ -20,21 +20,23 @@
 
 __author__ = "Nutti <nutti.metro at gmail.com>"
 __status__ = "production"
-__version__ = "6.2"
-__date__ = "31 Jul 2019"
+__version__ = "6.3"
+__date__ = "10 Aug 2020"
 
 
 bl_info = {
     "name": "Magic UV",
     "author": "Nutti, Mifth, Jace Priester, kgeogeo, mem, imdjs"
               "Keith (Wahooney) Boshoff, McBuff, MaxRobinot, "
-              "Alexander Milovsky",
-    "version": (6, 2, 0),
+              "Alexander Milovsky, Dusan Stevanovic",
+    "version": (6, 3, 0),
     "blender": (2, 80, 0),
     "location": "See Add-ons Preferences",
     "description": "UV Toolset. See Add-ons Preferences for details",
     "warning": "",
     "support": "COMMUNITY",
+    "wiki_url": "https://docs.blender.org/manual/en/dev/addons/"
+                "uv/magic_uv.html",
     "doc_url": "{BLENDER_MANUAL_URL}/addons/uv/magic_uv.html",
     "tracker_url": "https://github.com/nutti/Magic-UV",
     "category": "UV",
diff --git a/magic_uv/common.py b/magic_uv/common.py
index df3597be..11696667 100644
--- a/magic_uv/common.py
+++ b/magic_uv/common.py
@@ -20,8 +20,8 @@
 
 __author__ = "Nutti <nutti.metro at gmail.com>"
 __status__ = "production"
-__version__ = "6.2"
-__date__ = "31 Jul 2019"
+__version__ = "6.3"
+__date__ = "10 Aug 2020"
 
 from collections import defaultdict
 from pprint import pprint
@@ -244,15 +244,16 @@ def __parse_island(bm, face_idx, faces_left, island,
     Parse island
     """
 
-    if face_idx in faces_left:
-        faces_left.remove(face_idx)
-        island.append({'face': bm.faces[face_idx]})
-        for v in face_to_verts[face_idx]:
-            connected_faces = vert_to_faces[v]
-            if connected_faces:
+    faces_to_parse = [face_idx]
+    while faces_to_parse:
+        fidx = faces_to_parse.pop(0)
+        if fidx in faces_left:
+            faces_left.remove(fidx)
+            island.append({'face': bm.faces[fidx]})
+            for v in face_to_verts[fidx]:
+                connected_faces = vert_to_faces[v]
                 for cf in connected_faces:
-                    __parse_island(bm, cf, faces_left, island, face_to_verts,
-                                   vert_to_faces)
+                    faces_to_parse.append(cf)
 
 
 def __get_island(bm, face_to_verts, vert_to_faces):
@@ -351,18 +352,60 @@ def calc_polygon_3d_area(points):
     return 0.5 * area
 
 
-def measure_mesh_area(obj):
+def get_faces_list(bm, method, only_selected):
+    faces_list = []
+    if method == 'MESH':
+        if only_selected:
+            faces_list.append([f for f in bm.faces if f.select])
+        else:
+            faces_list.append([f for f in bm.faces])
+    elif method == 'UV ISLAND':
+        if not bm.loops.layers.uv:
+            return None
+        uv_layer = bm.loops.layers.uv.verify()
+        if only_selected:
+            faces = [f for f in bm.faces if f.select]
+            islands = get_island_info_from_faces(bm, faces, uv_layer)
+            for isl in islands:
+                faces_list.append([f["face"] for f in isl["faces"]])
+        else:
+            faces = [f for f in bm.faces]
+            islands = get_island_info_from_faces(bm, faces, uv_layer)
+            for isl in islands:
+                faces_list.append([f["face"] for f in isl["faces"]])
+    elif method == 'FACE':
+        if only_selected:
+            for f in bm.faces:
+                if f.select:
+                    faces_list.append([f])
+        else:
+            for f in bm.faces:
+                faces_list.append([f])
+    else:
+        raise ValueError("Invalid method: {}".format(method))
+
+    return faces_list
+
+
+def measure_mesh_area(obj, calc_method, only_selected):
     bm = bmesh.from_edit_mesh(obj.data)
     if check_version(2, 73, 0) >= 0:
         bm.verts.ensure_lookup_table()
         bm.edges.ensure_lookup_table()
         bm.faces.ensure_lookup_table()
 
-    sel_faces = [f for f in bm.faces if f.select]
+    faces_list = get_faces_list(bm, calc_method, only_selected)
 
-    # measure
+    areas = []
+    for faces in faces_list:
+        areas.append(measure_mesh_area_from_faces(faces))
+
+    return areas
+
+
+def measure_mesh_area_from_faces(faces):
     mesh_area = 0.0
-    for f in sel_faces:
+    for f in faces:
         verts = [l.vert.co for l in f.loops]
         f_mesh_area = calc_polygon_3d_area(verts)
         mesh_area = mesh_area + f_mesh_area
@@ -405,7 +448,7 @@ def find_image(obj, face=None, tex_layer=None):
 
     if len(images) >= 2:
         raise RuntimeError("Find more than 2 images")
-    if len(images) == 0:
+    if not images:
         return None
 
     return images[0]
@@ -428,40 +471,26 @@ def find_images(obj, face=None, tex_layer=None):
     return images
 
 
-def measure_uv_area(obj, method='FIRST', tex_size=None):
-    bm = bmesh.from_edit_mesh(obj.data)
-    if check_version(2, 73, 0) >= 0:
-        bm.verts.ensure_lookup_table()
-        bm.edges.ensure_lookup_table()
-        bm.faces.ensure_lookup_table()
-
-    if not bm.loops.layers.uv:
-        return None
-    uv_layer = bm.loops.layers.uv.verify()
-
-    tex_layer = find_texture_layer(bm)
-
-    sel_faces = [f for f in bm.faces if f.select]
-
-    # measure
+def measure_uv_area_from_faces(obj, faces, uv_layer, tex_layer,
+                               tex_selection_method, tex_size):
     uv_area = 0.0
-    for f in sel_faces:
+    for f in faces:
         uvs = [l[uv_layer].uv for l in f.loops]
         f_uv_area = calc_polygon_2d_area(uvs)
 
         # user specified
-        if method == 'USER_SPECIFIED' and tex_size is not None:
+        if tex_selection_method == 'USER_SPECIFIED' and tex_size is not None:
             img_size = tex_size
         # first texture if there are more than 2 textures assigned
         # to the object
-        elif method == 'FIRST':
+        elif tex_selection_method == 'FIRST':
             img = find_image(obj, f, tex_layer)
             # can not find from node, so we can not get texture size
             if not img:
                 return None
             img_size = img.size
         # average texture size
-        elif method == 'AVERAGE':
+        elif tex_selection_method == 'AVERAGE':
             imgs = find_images(obj, f, tex_layer)
             if not imgs:
                 return None
@@ -473,7 +502,7 @@ def measure_uv_area(obj, method='FIRST', tex_size=None):
             img_size = [img_size_total[0] / len(imgs),
                         img_size_total[1] / len(imgs)]
         # max texture size
-        elif method == 'MAX':
+        elif tex_selection_method == 'MAX':
             imgs = find_images(obj, f, tex_layer)
             if not imgs:
                 return None
@@ -484,7 +513,7 @@ def measure_uv_area(obj, method='FIRST', tex_size=None):
                                 max(img_size_max[1], img.size[1])]
             img_size = img_size_max
         # min texture size
-        elif method == 'MIN':
+        elif tex_selection_method == 'MIN':
             imgs = find_images(obj, f, tex_layer)
             if not imgs:
                 return None
@@ -495,13 +524,40 @@ def measure_uv_area(obj, method='FIRST', tex_size=None):
                                 min(img_size_min[1], img.size[1])]
             img_size = img_size_min
         else:
-            raise RuntimeError("Unexpected method: {}".format(method))
+            raise RuntimeError("Unexpected method: {}"
+                               .format(tex_selection_method))
 
-        uv_area = uv_area + f_uv_area * img_size[0] * img_size[1]
+        uv_area += f_uv_area * img_size[0] * img_size[1]
 
     return uv_area
 
 
+def measure_uv_area(obj, calc_method, tex_selection_method, tex_size,
+                    only_selected):
+    bm = bmesh.from_edit_mesh(obj.data)
+    if check_version(2, 73, 0) >= 0:
+        bm.verts.ensure_lookup_table()
+        bm.edges.ensure_lookup_table()
+        bm.faces.ensure_lookup_table()
+
+    if not bm.loops.layers.uv:
+        return None
+    uv_layer = bm.loops.layers.uv.verify()
+    tex_layer = find_texture_layer(bm)
+    faces_list = get_faces_list(bm, calc_method, only_selected)
+
+    # measure
+    uv_areas = []
+    for faces in faces_list:
+        uv_area = measure_uv_area_from_faces(
+            obj, faces, uv_layer, tex_layer, tex_selection_method, tex_size)
+        if uv_area is None:
+            return None
+        uv_areas.append(uv_area)
+
+    return uv_areas
+
+
 def diff_point_to_segment(a, b, p):
     ab = b - a
     normal_ab = ab.normalized()
@@ -520,43 +576,42 @@ def diff_point_to_segment(a, b, p):
 
 # get selected loop pair whose loops are connected each other
 def __get_loop_pairs(l, uv_layer):
-
-    def __get_loop_pairs_internal(l_, pairs_, uv_layer_, parsed_):
-        parsed_.append(l_)
-        for ll in l_.vert.link_loops:
+    pairs = []
+    parsed = []
+    loops_ready = [l]
+    while loops_ready:
+        l = loops_ready.pop(0)
+        parsed.append(l)
+        for ll in l.vert.link_loops:
             # forward direction
             lln = ll.link_loop_next
             # if there is same pair, skip it
             found = False
-            for p in pairs_:
+            for p in pairs:
                 if (ll in p) and (lln in p):
                     found = True
                     break
             # two loops must be selected
-            if ll[uv_layer_].select and lln[uv_layer_].select:
+            if ll[uv_layer].select and lln[uv_layer].select:
                 if not found:
-                    pairs_.append([ll, lln])
-                if lln not in parsed_:
-                    __get_loop_pairs_internal(lln, pairs_, uv_layer_, parsed_)
+                    pairs.append([ll, lln])
+                if (lln not in parsed) and (lln not in loops_ready):
+                    loops_ready.append(lln)
 
             # backward direction
             llp = ll.link_loop_prev
             # if there is same pair, skip it
             found = False
-            for p in pairs_:
+            for p in pairs:
                 if (ll in p) and (llp in p):
    

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-extensions-cvs mailing list