[Bf-extensions-cvs] SVN commit: /data/svn/bf-extensions [3672] contrib/py/scripts/addons/ mesh_copy_uvs_from_joined.py: addon to allow editing many UVs at once by temp joining mesh data, editing , then copying UV's back.

Campbell Barton ideasman42 at gmail.com
Thu Aug 9 10:32:57 CEST 2012


Revision: 3672
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-extensions&revision=3672
Author:   campbellbarton
Date:     2012-08-09 08:32:56 +0000 (Thu, 09 Aug 2012)
Log Message:
-----------
addon to allow editing many UVs at once by temp joining mesh data, editing, then copying UV's back.

original script by Sergey Sharybin with own minor edits.

Added Paths:
-----------
    contrib/py/scripts/addons/mesh_copy_uvs_from_joined.py

Added: contrib/py/scripts/addons/mesh_copy_uvs_from_joined.py
===================================================================
--- contrib/py/scripts/addons/mesh_copy_uvs_from_joined.py	                        (rev 0)
+++ contrib/py/scripts/addons/mesh_copy_uvs_from_joined.py	2012-08-09 08:32:56 UTC (rev 3672)
@@ -0,0 +1,215 @@
+# ##### 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; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  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 #####
+
+# <pep8 compliant>
+
+bl_info = {
+    "name": "Copy UV's from Joined",
+    "description": "Copy UV coordinates from the active joined mesh",
+    "author": "Sergey Sharybin",
+    "version": (0, 1),
+    "blender": (2, 63, 14),
+    "location": "Object mode 'Make Links' menu",
+    "wiki_url": "",
+    "tracker_url": "",
+    "category": "Object"}
+
+
+import bpy
+from bpy.types import Operator
+from mathutils import Vector
+
+FLT_MAX = 30000.0
+KEY_PRECISION = 1
+
+
+def MINMAX_INIT():
+    return (Vector((+FLT_MAX, +FLT_MAX, +FLT_MAX)),
+            Vector((-FLT_MAX, -FLT_MAX, -FLT_MAX)))
+
+
+def MINMAX_DO(min, max, vec):
+    for x in range(3):
+        if vec[x] < min[x]:
+            min[x] = vec[x]
+
+        if vec[x] > max[x]:
+            max[x] = vec[x]
+
+
+def getObjectAABB(obj):
+    min, max = MINMAX_INIT()
+
+    matrix = obj.matrix_world.copy()
+    for vec in obj.bound_box:
+        v = matrix * Vector(vec)
+        MINMAX_DO(min, max, v)
+
+    return min, max
+
+
+class  OBJECT_OT_copy_uv_from_joined(Operator):
+    """
+    Copy UVs from joined objects into originals
+    """
+
+    bl_idname = "object.copy_uv_from_joined"
+    bl_label = "Copy UVs from Joined"
+
+    def _findTranslation(self, obact, objects):
+        """
+        Find a translation from original objects to joined
+        """
+
+        bb_joined = getObjectAABB(obact)
+        bb_orig = MINMAX_INIT()
+
+        for ob in objects:
+            if ob != obact:
+                bb = getObjectAABB(ob)
+                MINMAX_DO(bb_orig[0], bb_orig[1], bb[0])
+                MINMAX_DO(bb_orig[0], bb_orig[1], bb[1])
+
+        return bb_joined[0] - bb_orig[0]
+
+    def _getPolygonMedian(self, me, poly):
+        median = Vector()
+        verts = me.vertices
+
+        for vert_index in poly.vertices:
+            median += verts[vert_index].co
+
+        median /= len(poly.vertices)
+
+        return median
+
+    def _getVertexLookupMap(self, obact, objects):
+        """
+        Create a vertex lookup map from joined object space to original object
+        """
+
+        map = {}
+
+        T = self._findTranslation(context)
+        obact = context.object
+
+        for ob in context.selected_objects:
+            if ob != obact:
+                me = ob.data
+                mat = ob.matrix_world
+                uv_layer = me.uv_layers.active
+
+                for poly in me.polygons:
+                    center = mat * self._getPolygonMedian(me, poly) + T
+                    center_key = center.to_tuple(KEY_PRECISION)
+
+                    for loop_index in poly.loop_indices:
+                        loop = me.loops[loop_index]
+                        vert = me.vertices[loop.vertex_index]
+                        vec = mat * vert.co + T
+
+                        key = (center_key, vec.to_tuple(KEY_PRECISION))
+
+                        if key not in map:
+                            map[key] = []
+
+                        map[key].append((center, vec, (uv_layer, loop_index)))
+
+        return map
+
+    def execute(self, context):
+        obact = context.object
+
+        # Check wether we're working with meshes
+        # other object types are not supported
+        if obact.type != 'MESH':
+            self.report({'ERROR'}, "Only meshes are supported")
+            return {'CANCELLED'}
+
+        objects = context.selected_objects
+
+        for obj in context.selected_objects:
+            if obj.type != 'MESH':
+                self.report({'ERROR'}, "Only meshes are supported")
+                return {'CANCELLED'}
+
+        uv_map = self._getVertexLookupMap(obact, objects)
+
+        me = obact.data
+        mat = obact.matrix_world.copy()
+        uv_layer = me.uv_layers.active
+
+        for poly in me.polygons:
+            center = mat * self._getPolygonMedian(me, poly)
+            center_key = center.to_tuple(KEY_PRECISION)
+
+            for loop_index in poly.loop_indices:
+                loop = me.loops[loop_index]
+                vert = me.vertices[loop.vertex_index]
+                vec = mat * vert.co
+
+                key = (center_key, vec.to_tuple(KEY_PRECISION))
+                check_list = uv_map.get(key)
+
+                if check_list is not None:
+                    new_uv = None
+                    closest_data = None
+
+                    dist = FLT_MAX
+                    for x in check_list:
+                        cur_center, cur_vec, data = x
+
+                        d1 = Vector(cur_center) - Vector(center)
+                        d2 = Vector(cur_vec) - Vector(vec)
+
+                        d = d1.length_squared + d2.length_squared
+
+                        if d < dist:
+                            closest_data = data
+                            dist = d
+
+                    if closest_data is not None:
+                        orig_uv_layer, orig_loop_index = closest_data
+                        new_uv = uv_layer.data[loop_index].uv
+                        orig_uv_layer.data[orig_loop_index].uv = new_uv
+                else:
+                    print("Failed to lookup %r" % key)
+
+        return {'FINISHED'}
+
+
+def menu_func(self, context):
+    self.layout.operator("OBJECT_OT_copy_uv_from_joined",
+                         text="Join as UVs (active to other selected)",
+                         icon="PLUGIN")
+
+
+def register():
+    bpy.utils.register_module(__name__)
+    
+    bpy.types.VIEW3D_MT_make_links.append(menu_func)
+    
+
+def unregister():
+    bpy.utils.unregister_module(__name__)
+
+    bpy.types.VIEW3D_MT_make_links.remove(menu_func)
+
+
+if __name__ == "__main__":
+    register()



More information about the Bf-extensions-cvs mailing list