Skip to content

Instantly share code, notes, and snippets.

@nutti
Last active August 27, 2016 09:28
Show Gist options
  • Save nutti/d3cf8a1c4b97496517349e3ab25074e9 to your computer and use it in GitHub Desktop.
Save nutti/d3cf8a1c4b97496517349e3ab25074e9 to your computer and use it in GitHub Desktop.
Unwrap Constraint
# ##### 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 #####
import bpy
import bmesh
from bpy.props import BoolProperty, EnumProperty, FloatProperty
bl_info = {
"name": "Unwrap Constraint",
"author": "Nutti",
"version": (0, 1),
"blender": (2, 77, 0),
"location": "View3D > U",
"description": "Unwrap while keeping uv coordinate",
"warning": "",
"support": "COMMUNITY",
"wiki_url": "",
"tracker_url": "",
"category": "UV"
}
class UnwrapConstraint(bpy.types.Operator):
bl_idname = "uv.unwrap_constraint"
bl_label = "Unwrap Constraint"
bl_description = "Unwrap while keeping uv coordinate"
bl_options = {'REGISTER', 'UNDO'}
# property for original unwrap
method = EnumProperty(
name="Method",
description="Unwrapping method",
items=[
('ANGLE_BASED', 'Angle Based', 'Angle Based'),
('CONFORMAL', 'Conformal', 'Conformal')],
default='ANGLE_BASED')
fill_holes = BoolProperty(
name="Fill Holes",
description="Virtual fill holes in meshes before unwrapping",
default=True)
correct_aspect = BoolProperty(
name="Correct Aspect",
description="Map UVs taking image aspect ratio into account",
default=True)
use_subsurf_data = BoolProperty(
name="Use Subsurf Modifier",
description="Map UVs taking vertex position after subsurf into account",
default=False)
margin = FloatProperty(
name="Margin",
description="Space between islands",
max=1.0,
min=0.0,
default=0.001)
# property for this operation
x_const = BoolProperty(
name="X-Constraint",
description="Keep UV X-axis coordinate",
default=False)
y_const = BoolProperty(
name="Y-Constraint",
description="Keep UV Y-axis coordinate",
default=False)
def execute(self, context):
obj = bpy.context.active_object
bm = bmesh.from_edit_mesh(obj.data)
bm.faces.ensure_lookup_table()
if not bm.loops.layers.uv:
self.report(
{'WARNING'}, "Object must have more than one UV map")
return {'CANCELLED'}
uv_layer = bm.loops.layers.uv.verify()
# get original UV coordinate
faces = [f for f in bm.faces if f.select]
uv_list = []
for f in faces:
uvs = [l[uv_layer].uv.copy() for l in f.loops]
uv_list.append(uvs)
# unwrap
bpy.ops.uv.unwrap(
method=self.method,
fill_holes=self.fill_holes,
correct_aspect=self.correct_aspect,
use_subsurf_data=self.use_subsurf_data,
margin=self.margin)
# when X/Y-Constraint is checked, revert original coordinate
for f, uvs in zip(faces, uv_list):
for l, uv in zip(f.loops, uvs):
if self.x_const:
l[uv_layer].uv.x = uv.x
if self.y_const:
l[uv_layer].uv.y = uv.y
# update mesh
bmesh.update_edit_mesh(obj.data)
return {'FINISHED'}
def view3d_uvmap_menu_fn(self, context):
self.layout.separator()
self.layout.operator(UnwrapConstraint.bl_idname, icon="PLUGIN")
def register():
bpy.utils.register_module(__name__)
bpy.types.VIEW3D_MT_uv_map.append(view3d_uvmap_menu_fn)
def unregister():
bpy.utils.unregister_module(__name__)
bpy.types.VIEW3D_MT_uv_map.remove(view3d_uvmap_menu_fn)
if __name__ == "__main__":
register()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment