3 # ##### BEGIN GPL LICENSE BLOCK #####
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software Foundation,
17 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 # ##### END GPL LICENSE BLOCK #####
21 __author__
= "Nutti <nutti.metro@gmail.com>"
22 __status__
= "production"
24 __date__
= "24 Feb 2018"
28 from bpy
.props
import (
36 def memorize_view_3d_mode(fn
):
37 def __memorize_view_3d_mode(self
, context
):
38 mode_orig
= bpy
.context
.object.mode
39 result
= fn(self
, context
)
40 bpy
.ops
.object.mode_set(mode
=mode_orig
)
42 return __memorize_view_3d_mode
45 class MUV_CPUVObjCopyUV(bpy
.types
.Operator
):
47 Operation class: Copy UV coordinate per object
50 bl_idname
= "object.muv_cpuv_obj_copy_uv"
52 bl_description
= "Copy UV coordinate"
53 bl_options
= {'REGISTER', 'UNDO'}
55 uv_map
= StringProperty(options
={'HIDDEN'})
57 @memorize_view_3d_mode
58 def execute(self
, context
):
59 props
= context
.scene
.muv_props
.cpuv_obj
61 self
.report({'INFO'}, "Copy UV coordinate per object")
65 "Copy UV coordinate per object (UV map:%s)" % (self
.uv_map
))
66 bpy
.ops
.object.mode_set(mode
='EDIT')
68 obj
= context
.active_object
69 bm
= bmesh
.from_edit_mesh(obj
.data
)
70 if common
.check_version(2, 73, 0) >= 0:
71 bm
.faces
.ensure_lookup_table()
75 if not bm
.loops
.layers
.uv
:
77 {'WARNING'}, "Object must have more than one UV map")
79 uv_layer
= bm
.loops
.layers
.uv
.verify()
81 uv_layer
= bm
.loops
.layers
.uv
[self
.uv_map
]
85 props
.src_pin_uvs
= []
88 uvs
= [l
[uv_layer
].uv
.copy() for l
in face
.loops
]
89 pin_uvs
= [l
[uv_layer
].pin_uv
for l
in face
.loops
]
90 seams
= [l
.edge
.seam
for l
in face
.loops
]
91 props
.src_uvs
.append(uvs
)
92 props
.src_pin_uvs
.append(pin_uvs
)
93 props
.src_seams
.append(seams
)
95 self
.report({'INFO'}, "%s's UV coordinates are copied" % (obj
.name
))
100 class MUV_CPUVObjCopyUVMenu(bpy
.types
.Menu
):
102 Menu class: Copy UV coordinate per object
105 bl_idname
= "object.muv_cpuv_obj_copy_uv_menu"
107 bl_description
= "Copy UV coordinate per object"
112 uv_maps
= bpy
.context
.active_object
.data
.uv_textures
.keys()
113 layout
.operator(MUV_CPUVObjCopyUV
.bl_idname
, text
="[Default]")\
116 layout
.operator(MUV_CPUVObjCopyUV
.bl_idname
, text
=m
).uv_map
= m
119 class MUV_CPUVObjPasteUV(bpy
.types
.Operator
):
121 Operation class: Paste UV coordinate per object
124 bl_idname
= "object.muv_cpuv_obj_paste_uv"
125 bl_label
= "Paste UV"
126 bl_description
= "Paste UV coordinate"
127 bl_options
= {'REGISTER', 'UNDO'}
129 uv_map
= StringProperty(options
={'HIDDEN'})
130 copy_seams
= BoolProperty(
132 description
="Copy Seams",
136 @memorize_view_3d_mode
137 def execute(self
, context
):
138 props
= context
.scene
.muv_props
.cpuv_obj
139 if not props
.src_uvs
or not props
.src_pin_uvs
:
140 self
.report({'WARNING'}, "Need copy UV at first")
143 for o
in bpy
.data
.objects
:
144 if not hasattr(o
.data
, "uv_textures") or not o
.select
:
147 bpy
.ops
.object.mode_set(mode
='OBJECT')
148 bpy
.context
.scene
.objects
.active
= o
149 bpy
.ops
.object.mode_set(mode
='EDIT')
151 obj
= context
.active_object
152 bm
= bmesh
.from_edit_mesh(obj
.data
)
153 if common
.check_version(2, 73, 0) >= 0:
154 bm
.faces
.ensure_lookup_table()
156 if (self
.uv_map
== "" or
157 self
.uv_map
not in bm
.loops
.layers
.uv
.keys()):
158 self
.report({'INFO'}, "Paste UV coordinate per object")
162 "Paste UV coordinate per object (UV map: %s)"
166 if (self
.uv_map
== "" or
167 self
.uv_map
not in bm
.loops
.layers
.uv
.keys()):
168 if not bm
.loops
.layers
.uv
:
170 {'WARNING'}, "Object must have more than one UV map")
172 uv_layer
= bm
.loops
.layers
.uv
.verify()
174 uv_layer
= bm
.loops
.layers
.uv
[self
.uv_map
]
180 dest_face_indices
= []
181 for face
in bm
.faces
:
182 dest_face_indices
.append(face
.index
)
183 uvs
= [l
[uv_layer
].uv
.copy() for l
in face
.loops
]
184 pin_uvs
= [l
[uv_layer
].pin_uv
for l
in face
.loops
]
185 seams
= [l
.edge
.seam
for l
in face
.loops
]
187 dest_pin_uvs
.append(pin_uvs
)
188 dest_seams
.append(seams
)
189 if len(props
.src_uvs
) != len(dest_uvs
):
192 "Number of faces is different from copied " +
194 % (len(props
.src_uvs
), len(dest_uvs
))
199 for i
, idx
in enumerate(dest_face_indices
):
200 suv
= props
.src_uvs
[i
]
201 spuv
= props
.src_pin_uvs
[i
]
202 ss
= props
.src_seams
[i
]
204 if len(suv
) != len(duv
):
205 self
.report({'WARNING'}, "Some faces are different size")
207 suvs_fr
= [uv
for uv
in suv
]
208 spuvs_fr
= [pin_uv
for pin_uv
in spuv
]
209 ss_fr
= [s
for s
in ss
]
211 for l
, suv
, spuv
, ss
in zip(
212 bm
.faces
[idx
].loops
, suvs_fr
, spuvs_fr
, ss_fr
):
214 l
[uv_layer
].pin_uv
= spuv
215 if self
.copy_seams
is True:
218 bmesh
.update_edit_mesh(obj
.data
)
219 if self
.copy_seams
is True:
220 obj
.data
.show_edge_seams
= True
223 {'INFO'}, "%s's UV coordinates are pasted" % (obj
.name
))
228 class MUV_CPUVObjPasteUVMenu(bpy
.types
.Menu
):
230 Menu class: Paste UV coordinate per object
233 bl_idname
= "object.muv_cpuv_obj_paste_uv_menu"
234 bl_label
= "Paste UV"
235 bl_description
= "Paste UV coordinate per object"
237 def draw(self
, context
):
242 for obj
in bpy
.data
.objects
:
243 if hasattr(obj
.data
, "uv_textures") and obj
.select
:
244 uv_maps
.extend(obj
.data
.uv_textures
.keys())
245 uv_maps
= list(set(uv_maps
))
246 ops
= layout
.operator(MUV_CPUVObjPasteUV
.bl_idname
, text
="[Default]")
248 ops
.copy_seams
= sc
.muv_cpuv_copy_seams
250 ops
= layout
.operator(MUV_CPUVObjPasteUV
.bl_idname
, text
=m
)
252 ops
.copy_seams
= sc
.muv_cpuv_copy_seams