Cleanup: Node Wrangler: preview_node operator
[blender-addons.git] / magic_uv / op / unwrap_constraint.py
blobf91e4fd9205152538ede9750ccebc6e2e979bec7
1 # SPDX-FileCopyrightText: 2017-2022 Blender Foundation
3 # SPDX-License-Identifier: GPL-2.0-or-later
5 __author__ = "Nutti <nutti.metro@gmail.com>"
6 __status__ = "production"
7 __version__ = "6.6"
8 __date__ = "22 Apr 2022"
10 import bpy
11 from bpy.props import (
12 BoolProperty,
13 EnumProperty,
14 FloatProperty,
16 import bmesh
18 from .. import common
19 from ..utils.bl_class_registry import BlClassRegistry
20 from ..utils.property_class_registry import PropertyClassRegistry
21 from ..utils import compatibility as compat
24 def _is_valid_context(context):
25 # only 'VIEW_3D' space is allowed to execute
26 if not common.is_valid_space(context, ['VIEW_3D']):
27 return False
29 objs = common.get_uv_editable_objects(context)
30 if not objs:
31 return False
33 # only edit mode is allowed to execute
34 if context.object.mode != 'EDIT':
35 return False
37 return True
40 @PropertyClassRegistry()
41 class _Properties:
42 idname = "unwrap_constraint"
44 @classmethod
45 def init_props(cls, scene):
46 scene.muv_unwrap_constraint_enabled = BoolProperty(
47 name="Unwrap Constraint Enabled",
48 description="Unwrap Constraint is enabled",
49 default=False
51 scene.muv_unwrap_constraint_u_const = BoolProperty(
52 name="U-Constraint",
53 description="Keep UV U-axis coordinate",
54 default=False
56 scene.muv_unwrap_constraint_v_const = BoolProperty(
57 name="V-Constraint",
58 description="Keep UV V-axis coordinate",
59 default=False
62 @classmethod
63 def del_props(cls, scene):
64 del scene.muv_unwrap_constraint_enabled
65 del scene.muv_unwrap_constraint_u_const
66 del scene.muv_unwrap_constraint_v_const
69 @BlClassRegistry(legacy=True)
70 @compat.make_annotations
71 class MUV_OT_UnwrapConstraint(bpy.types.Operator):
72 """
73 Operation class: Unwrap with constrain UV coordinate
74 """
76 bl_idname = "uv.muv_unwrap_constraint"
77 bl_label = "Unwrap Constraint"
78 bl_description = "Unwrap while keeping uv coordinate"
79 bl_options = {'REGISTER', 'UNDO'}
81 # property for original unwrap
82 method = EnumProperty(
83 name="Method",
84 description="Unwrapping method",
85 items=[
86 ('ANGLE_BASED', 'Angle Based', 'Angle Based'),
87 ('CONFORMAL', 'Conformal', 'Conformal')
89 default='ANGLE_BASED')
90 fill_holes = BoolProperty(
91 name="Fill Holes",
92 description="Virtual fill holes in meshes before unwrapping",
93 default=True)
94 correct_aspect = BoolProperty(
95 name="Correct Aspect",
96 description="Map UVs taking image aspect ratio into account",
97 default=True)
98 use_subsurf_data = BoolProperty(
99 name="Use Subsurf Modifier",
100 description="""Map UVs taking vertex position after subsurf
101 into account""",
102 default=False)
103 margin = FloatProperty(
104 name="Margin",
105 description="Space between islands",
106 max=1.0,
107 min=0.0,
108 default=0.001)
110 # property for this operation
111 u_const = BoolProperty(
112 name="U-Constraint",
113 description="Keep UV U-axis coordinate",
114 default=False
116 v_const = BoolProperty(
117 name="V-Constraint",
118 description="Keep UV V-axis coordinate",
119 default=False
122 @classmethod
123 def poll(cls, context):
124 # we can not get area/space/region from console
125 if common.is_console_mode():
126 return True
127 return _is_valid_context(context)
129 def execute(self, context):
130 objs = common.get_uv_editable_objects(context)
132 uv_list = {} # { Object: uv_list }
133 for obj in objs:
134 bm = bmesh.from_edit_mesh(obj.data)
135 if common.check_version(2, 73, 0) >= 0:
136 bm.faces.ensure_lookup_table()
138 # bpy.ops.uv.unwrap() makes one UV map at least
139 if not bm.loops.layers.uv:
140 self.report({'WARNING'},
141 "Object {} must have more than one UV map"
142 .format(obj.name))
143 return {'CANCELLED'}
144 uv_layer = bm.loops.layers.uv.verify()
146 # get original UV coordinate
147 faces = [f for f in bm.faces if f.select]
148 uv_list[obj] = []
149 for f in faces:
150 uvs = [l[uv_layer].uv.copy() for l in f.loops]
151 uv_list[obj].append(uvs)
153 # unwrap
154 bpy.ops.uv.unwrap(
155 method=self.method,
156 fill_holes=self.fill_holes,
157 correct_aspect=self.correct_aspect,
158 use_subsurf_data=self.use_subsurf_data,
159 margin=self.margin)
161 # when U/V-Constraint is checked, revert original coordinate
162 for obj in objs:
163 bm = bmesh.from_edit_mesh(obj.data)
164 if common.check_version(2, 73, 0) >= 0:
165 bm.faces.ensure_lookup_table()
166 uv_layer = bm.loops.layers.uv.verify()
167 faces = [f for f in bm.faces if f.select]
169 for f, uvs in zip(faces, uv_list[obj]):
170 for l, uv in zip(f.loops, uvs):
171 if self.u_const:
172 l[uv_layer].uv.x = uv.x
173 if self.v_const:
174 l[uv_layer].uv.y = uv.y
176 # update mesh
177 bmesh.update_edit_mesh(obj.data)
179 return {'FINISHED'}