[Bf-extensions-cvs] [a0e7faa] master: added uv_align_distribute.py(first commit)

Luca Carella noreply at git.blender.org
Mon Jul 28 19:04:22 CEST 2014


Commit: a0e7faaa800e3a18d0b3d72fb7139fd617e9484e
Author: Luca Carella
Date:   Mon Jul 28 18:12:24 2014 +0200
Branches: master
https://developer.blender.org/rBACa0e7faaa800e3a18d0b3d72fb7139fd617e9484e

added  uv_align_distribute.py(first commit)

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

A	uv_align_distribute.py

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

diff --git a/uv_align_distribute.py b/uv_align_distribute.py
new file mode 100644
index 0000000..d117f9d
--- /dev/null
+++ b/uv_align_distribute.py
@@ -0,0 +1,1066 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; version 2
+#  of the License.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software Foundation,
+#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+bl_info = {
+    "name": "UV Align/Distribute",
+    "author": "Rebellion (Luca Carella)",
+    "version": (1, 1),
+    "blender": (2, 7, 1),
+    "location": "UV/Image editor > Tool Panel, UV/Image editor UVs > menu",
+    "description": "Set of tools to help UV alignment\distribution",
+    "warning": "",
+    "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/Scripts/UV/UV_Align_Distribution",
+    "category": "UV"}
+
+import math
+from collections import defaultdict
+
+import bmesh
+import bpy
+import mathutils
+from bpy.props import EnumProperty, BoolProperty, FloatProperty
+
+
+# Globals:
+bpy.types.Scene.relativeItems = EnumProperty(
+    items=[
+        ('UV_SPACE', 'Uv Space', 'Align to UV space'),
+        ('ACTIVE', 'Active Face', 'Align to active face\island'),
+        ('CURSOR', 'Cursor', 'Align to cursor')],
+    name="Relative to")
+
+bpy.types.Scene.selectionAsGroup = BoolProperty(
+    name="Selection as group",
+    description="Treat selection as group",
+    default=False)
+
+bm = None
+uvlayer = None
+
+
+def InitBMesh():
+    global bm
+    global uvlayer
+    bm = bmesh.from_edit_mesh(bpy.context.edit_object.data)
+    uvlayer = bm.loops.layers.uv.active
+
+
+def update():
+    bmesh.update_edit_mesh(bpy.context.edit_object.data, False, False)
+    # bm.to_mesh(bpy.context.object.data)
+    # bm.free()
+
+
+def GBBox(islands):
+    minX, minY = +1000
+    maxX, maxY = -1000
+    for island in islands:
+        for face_id in island:
+            face = bm.faces[face_id]
+            for loop in face.loops:
+                u, v = loop[uvlayer].uv
+                minX = min(u, minX)
+                minY = min(v, minY)
+                maxX = max(u, maxX)
+                maxY = max(v, maxY)
+
+    return mathutils.Vector((minX, minY)), mathutils.Vector((maxX, maxY))
+
+
+def GBBoxCenter(islands):
+    minX, minY = +1000
+    maxX, maxY = -1000
+    for island in islands:
+        for face_id in island:
+            face = bm.faces[face_id]
+            for loop in face.loops:
+                u, v = loop[uvlayer].uv
+                minX = min(u, minX)
+                minY = min(v, minY)
+                maxX = max(u, maxX)
+                maxY = max(v, maxY)
+
+    return (mathutils.Vector((minX, minY)) +
+            mathutils.Vector((maxX, maxY))) / 2
+
+
+def BBox(island):
+    minX, minY = +1000
+    maxX, maxY = -1000
+    # for island in islands:
+    # print(island)
+    for face_id in island:
+        face = bm.faces[face_id]
+        for loop in face.loops:
+            u, v = loop[uvlayer].uv
+            minX = min(u, minX)
+            minY = min(v, minY)
+            maxX = max(u, maxX)
+            maxY = max(v, maxY)
+
+    return mathutils.Vector((minX, minY)), mathutils.Vector((maxX, maxY))
+
+
+def BBoxCenter(island):
+    minX, minY = +1000
+    maxX, maxY = -1000
+    # for island in islands:
+    for face_id in island:
+        face = bm.faces[face_id]
+        for loop in face.loops:
+            u, v = loop[uvlayer].uv
+            minX = min(u, minX)
+            minY = min(v, minY)
+            maxX = max(u, maxX)
+            maxY = max(v, maxY)
+
+    return (mathutils.Vector((minX, minY)) +
+            mathutils.Vector((maxX, maxY))) / 2
+
+
+def islandAngle(island):
+    uvList = []
+    for face_id in island:
+        face = bm.faces[face_id]
+        for loop in face.loops:
+            uv = loop[bm.loops.layers.uv.active].uv
+            uvList.append(uv)
+
+    angle = math.degrees(mathutils.geometry.box_fit_2d(uvList))
+    return angle
+
+
+def moveIslands(vector, island):
+    for face_id in island:
+        face = bm.faces[face_id]
+        for loop in face.loops:
+            loop[bm.loops.layers.uv.active].uv += vector
+
+
+def rotateIsland(island, angle):
+    rad = math.radians(angle)
+    center = BBoxCenter(island)
+
+    for face_id in island:
+        face = bm.faces[face_id]
+        for loop in face.loops:
+            uv_act = bm.loops.layers.uv.active
+            x, y = loop[uv_act].uv
+            xt = x - center.x
+            yt = y - center.y
+            xr = (xt * math.cos(rad)) - (yt * math.sin(rad))
+            yr = (xt * math.sin(rad)) + (yt * math.cos(rad))
+            # loop[bm.loops.layers.uv.active].uv = trans
+            loop[bm.loops.layers.uv.active].uv.x = xr + center.x
+            loop[bm.loops.layers.uv.active].uv.y = yr + center.y
+            # print('fired')
+
+
+def scaleIsland(island, scaleX, scaleY):
+    scale = mathutils.Vector((scaleX, scaleY))
+    center = BBoxCenter(island)
+
+    for face_id in island:
+        face = bm.faces[face_id]
+        for loop in face.loops:
+            x = loop[bm.loops.layers.uv.active].uv.x
+            y = loop[bm.loops.layers.uv.active].uv.y
+            xt = x - center.x
+            yt = y - center.y
+            xs = xt * scaleX
+            ys = yt * scaleY
+            loop[bm.loops.layers.uv.active].uv.x = xs + center.x
+            loop[bm.loops.layers.uv.active].uv.y = ys + center.y
+
+
+def vectorDistance(vector1, vector2):
+    return math.sqrt(
+        math.pow((vector2.x - vector1.x), 2) +
+        math.pow((vector2.y - vector1.y), 2))
+
+
+def matchIsland(active, thresold, island):
+    for active_face_id in active:
+        active_face = bm.faces[active_face_id]
+
+        for active_loop in active_face.loops:
+            activeUVvert = active_loop[bm.loops.layers.uv.active].uv
+
+            for face_id in island:
+                face = bm.faces[face_id]
+
+                for loop in face.loops:
+                    selectedUVvert = loop[bm.loops.layers.uv.active].uv
+                    dist = vectorDistance(selectedUVvert, activeUVvert)
+
+                    if dist <= thresold:
+                        loop[bm.loops.layers.uv.active].uv = activeUVvert
+
+
+def getTargetPoint(context, islands):
+    if context.scene.relativeItems == 'UV_SPACE':
+        return mathutils.Vector((0.0, 0.0)), mathutils.Vector((1.0, 1.0))
+    elif context.scene.relativeItems == 'ACTIVE':
+        activeIsland = islands.activeIsland()
+        if not activeIsland:
+            return None
+        else:
+            return BBox(activeIsland)
+    elif context.scene.relativeItems == 'CURSOR':
+        return context.space_data.cursor_location,\
+            context.space_data.cursor_location
+
+
+def IslandSpatialSortX(islands):
+    spatialSort = []
+    for island in islands:
+        spatialSort.append((BBoxCenter(island).x, island))
+    spatialSort.sort()
+    return spatialSort
+
+
+def IslandSpatialSortY(islands):
+    spatialSort = []
+    for island in islands:
+        spatialSort.append((BBoxCenter(island).y, island))
+    spatialSort.sort()
+    return spatialSort
+
+
+def averageIslandDist(islands):
+    distX = 0
+    distY = 0
+    counter = 0
+
+    for i in range(len(islands)):
+        elem1 = BBox(islands[i][1])[1]
+        try:
+            elem2 = BBox(islands[i + 1][1])[0]
+            counter += 1
+        except:
+            break
+
+        distX += elem2.x - elem1.x
+        distY += elem2.y - elem1.y
+
+    avgDistX = distX / counter
+    avgDistY = distY / counter
+    return mathutils.Vector((avgDistX, avgDistY))
+
+
+def islandSize(island):
+    bbox = BBox(island)
+    sizeX = bbox[1].x - bbox[0].x
+    sizeY = bbox[1].y - bbox[0].y
+
+    return sizeX, sizeY
+
+
+class MakeIslands():
+
+    def __init__(self):
+        InitBMesh()
+        global bm
+        global uvlayer
+
+        self.face_to_verts = defaultdict(set)
+        self.vert_to_faces = defaultdict(set)
+        self.selectedIsland = set()
+
+        for face in bm.faces:
+            for loop in face.loops:
+                id = loop[uvlayer].uv.to_tuple(5), loop.vert.index
+                self.face_to_verts[face.index].add(id)
+                self.vert_to_faces[id].add(face.index)
+                if face.select:
+                    if loop[uvlayer].select:
+                        self.selectedIsland.add(face.index)
+
+    def addToIsland(self, face_id):
+        if face_id in self.faces_left:
+            # add the face itself
+            self.current_island.append(face_id)
+            self.faces_left.remove(face_id)
+            # and add all faces that share uvs with this face
+            verts = self.face_to_verts[face_id]
+            for vert in verts:
+                # print('looking at vert {}'.format(vert))
+                connected_faces = self.vert_to_faces[vert]
+                if connected_faces:
+                    for face in connected_faces:
+                        self.addToIsland(face)
+
+    def getIslands(self):
+        self.islands = []
+        self.faces_left = set(self.face_to_verts.keys())
+        while len(self.faces_left) > 0:
+            face_id = list(self.faces_left)[0]
+            self.current_island = []
+            self.addToIsland(face_id)
+            self.islands.append(self.current_island)
+
+        return self.islands
+
+    def activeIsland(self):
+        for island in self.islands:
+            try:
+                if bm.faces.active.index in island:
+                    return island
+            except:
+                return None
+
+    def selectedIslands(self):
+        _selectedIslands = []
+        for 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-extensions-cvs mailing list