139 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			139 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
# ##### 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-80 compliant>
 | 
						|
 | 
						|
import bpy
 | 
						|
from bpy.types import Operator
 | 
						|
 | 
						|
from bpy.props import EnumProperty
 | 
						|
 | 
						|
 | 
						|
class MeshMirrorUV(Operator):
 | 
						|
    """Copy mirror UV coordinates on the X axis based on a mirrored mesh"""
 | 
						|
    bl_idname = "mesh.faces_mirror_uv"
 | 
						|
    bl_label = "Copy Mirrored UV coords"
 | 
						|
    bl_options = {'REGISTER', 'UNDO'}
 | 
						|
 | 
						|
    direction = EnumProperty(
 | 
						|
            name="Axis Direction",
 | 
						|
            items=(('POSITIVE', "Positive", ""),
 | 
						|
                   ('NEGATIVE', "Negative", "")),
 | 
						|
            )
 | 
						|
 | 
						|
    @classmethod
 | 
						|
    def poll(cls, context):
 | 
						|
        obj = context.active_object
 | 
						|
        return (obj and obj.type == 'MESH' and obj.data.uv_textures.active)
 | 
						|
 | 
						|
    def execute(self, context):
 | 
						|
        DIR = (self.direction == 'NEGATIVE')
 | 
						|
 | 
						|
        ob = context.active_object
 | 
						|
        is_editmode = (ob.mode == 'EDIT')
 | 
						|
        if is_editmode:
 | 
						|
            bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
 | 
						|
 | 
						|
        mesh = ob.data
 | 
						|
 | 
						|
        # mirror lookups
 | 
						|
        mirror_gt = {}
 | 
						|
        mirror_lt = {}
 | 
						|
 | 
						|
        vcos = (v.co.to_tuple(5) for v in mesh.vertices)
 | 
						|
 | 
						|
        for i, co in enumerate(vcos):
 | 
						|
            if co[0] >= 0.0:
 | 
						|
                mirror_gt[co] = i
 | 
						|
            if co[0] <= 0.0:
 | 
						|
                mirror_lt[co] = i
 | 
						|
 | 
						|
        #for i, v in enumerate(mesh.vertices):
 | 
						|
        vmap = {}
 | 
						|
        for mirror_a, mirror_b in ((mirror_gt, mirror_lt),
 | 
						|
                                   (mirror_lt, mirror_gt)):
 | 
						|
            for co, i in mirror_a.items():
 | 
						|
                nco = (-co[0], co[1], co[2])
 | 
						|
                j = mirror_b.get(nco)
 | 
						|
                if j is not None:
 | 
						|
                    vmap[i] = j
 | 
						|
 | 
						|
        polys = mesh.polygons
 | 
						|
        loops = mesh.loops
 | 
						|
        verts = mesh.vertices
 | 
						|
        uv_loops = mesh.uv_layers.active.data
 | 
						|
        nbr_polys = len(polys)
 | 
						|
 | 
						|
        mirror_pm = {}
 | 
						|
        pmap = {}
 | 
						|
        puvs = [None] * nbr_polys
 | 
						|
        puvs_cpy = [None] * nbr_polys
 | 
						|
        puvsel = [None] * nbr_polys
 | 
						|
        pcents = [None] * nbr_polys
 | 
						|
        vidxs = [None] * nbr_polys
 | 
						|
        for i, p in enumerate(polys):
 | 
						|
            lstart = lend = p.loop_start
 | 
						|
            lend += p.loop_total
 | 
						|
            puvs[i] = tuple(uv.uv for uv in uv_loops[lstart:lend])
 | 
						|
            puvs_cpy[i] = tuple(uv.copy() for uv in puvs[i])
 | 
						|
            puvsel[i] = (False not in
 | 
						|
                         (uv.select for uv in uv_loops[lstart:lend]))
 | 
						|
            # Vert idx of the poly.
 | 
						|
            vidxs[i] = tuple(l.vertex_index for l in loops[lstart:lend])
 | 
						|
            # As we have no poly.center yet...
 | 
						|
            pcents[i] = tuple(map(lambda x: x / p.loop_total,
 | 
						|
                                  map(sum, zip(*(verts[idx].co
 | 
						|
                                                 for idx in vidxs[i])))))
 | 
						|
            # Preparing next step finding matching polys.
 | 
						|
            mirror_pm[tuple(sorted(vidxs[i]))] = i
 | 
						|
 | 
						|
        for i in range(nbr_polys):
 | 
						|
            # Find matching mirror poly.
 | 
						|
            tvidxs = [vmap.get(j) for j in vidxs[i]]
 | 
						|
            if None not in tvidxs:
 | 
						|
                tvidxs.sort()
 | 
						|
                j = mirror_pm.get(tuple(tvidxs))
 | 
						|
                if j is not None:
 | 
						|
                    pmap[i] = j
 | 
						|
 | 
						|
        for i, j in pmap.items():
 | 
						|
            if not puvsel[i] or not puvsel[j]:
 | 
						|
                continue
 | 
						|
            elif DIR == 0 and pcents[i][0] < 0.0:
 | 
						|
                continue
 | 
						|
            elif DIR == 1 and pcents[i][0] > 0.0:
 | 
						|
                continue
 | 
						|
 | 
						|
            # copy UVs
 | 
						|
            uv1 = puvs[i]
 | 
						|
            uv2 = puvs_cpy[j]
 | 
						|
 | 
						|
            # get the correct rotation
 | 
						|
            v1 = vidxs[j]
 | 
						|
            v2 = tuple(vmap[k] for k in vidxs[i])
 | 
						|
 | 
						|
            if len(v1) == len(v2):
 | 
						|
                for k in range(len(v1)):
 | 
						|
                    k_map = v1.index(v2[k])
 | 
						|
                    uv1[k].xy = - (uv2[k_map].x - 0.5) + 0.5, uv2[k_map].y
 | 
						|
 | 
						|
        if is_editmode:
 | 
						|
            bpy.ops.object.mode_set(mode='EDIT', toggle=False)
 | 
						|
 | 
						|
        return {'FINISHED'}
 |