1 # SPDX-License-Identifier: GPL-2.0-or-later
3 __author__
= "Nutti <nutti.metro@gmail.com>"
4 __status__
= "production"
6 __date__
= "6 Mar 2021"
9 from bpy
.props
import (
17 from ..utils
.bl_class_registry
import BlClassRegistry
18 from ..utils
.property_class_registry
import PropertyClassRegistry
19 from ..utils
import compatibility
as compat
22 def _is_valid_context(context
):
23 objs
= common
.get_uv_editable_objects(context
)
27 # only edit mode is allowed to execute
28 if context
.object.mode
!= 'EDIT':
31 # only 'VIEW_3D' space is allowed to execute
32 if not common
.is_valid_space(context
, ['VIEW_3D']):
38 @PropertyClassRegistry()
40 idname
= "unwrap_constraint"
43 def init_props(cls
, scene
):
44 scene
.muv_unwrap_constraint_enabled
= BoolProperty(
45 name
="Unwrap Constraint Enabled",
46 description
="Unwrap Constraint is enabled",
49 scene
.muv_unwrap_constraint_u_const
= BoolProperty(
51 description
="Keep UV U-axis coordinate",
54 scene
.muv_unwrap_constraint_v_const
= BoolProperty(
56 description
="Keep UV V-axis coordinate",
61 def del_props(cls
, scene
):
62 del scene
.muv_unwrap_constraint_enabled
63 del scene
.muv_unwrap_constraint_u_const
64 del scene
.muv_unwrap_constraint_v_const
67 @BlClassRegistry(legacy
=True)
68 @compat.make_annotations
69 class MUV_OT_UnwrapConstraint(bpy
.types
.Operator
):
71 Operation class: Unwrap with constrain UV coordinate
74 bl_idname
= "uv.muv_unwrap_constraint"
75 bl_label
= "Unwrap Constraint"
76 bl_description
= "Unwrap while keeping uv coordinate"
77 bl_options
= {'REGISTER', 'UNDO'}
79 # property for original unwrap
80 method
= EnumProperty(
82 description
="Unwrapping method",
84 ('ANGLE_BASED', 'Angle Based', 'Angle Based'),
85 ('CONFORMAL', 'Conformal', 'Conformal')
87 default
='ANGLE_BASED')
88 fill_holes
= BoolProperty(
90 description
="Virtual fill holes in meshes before unwrapping",
92 correct_aspect
= BoolProperty(
93 name
="Correct Aspect",
94 description
="Map UVs taking image aspect ratio into account",
96 use_subsurf_data
= BoolProperty(
97 name
="Use Subsurf Modifier",
98 description
="""Map UVs taking vertex position after subsurf
101 margin
= FloatProperty(
103 description
="Space between islands",
108 # property for this operation
109 u_const
= BoolProperty(
111 description
="Keep UV U-axis coordinate",
114 v_const
= BoolProperty(
116 description
="Keep UV V-axis coordinate",
121 def poll(cls
, context
):
122 # we can not get area/space/region from console
123 if common
.is_console_mode():
125 return _is_valid_context(context
)
127 def execute(self
, context
):
128 objs
= common
.get_uv_editable_objects(context
)
130 uv_list
= {} # { Object: uv_list }
132 bm
= bmesh
.from_edit_mesh(obj
.data
)
133 if common
.check_version(2, 73, 0) >= 0:
134 bm
.faces
.ensure_lookup_table()
136 # bpy.ops.uv.unwrap() makes one UV map at least
137 if not bm
.loops
.layers
.uv
:
138 self
.report({'WARNING'},
139 "Object {} must have more than one UV map"
142 uv_layer
= bm
.loops
.layers
.uv
.verify()
144 # get original UV coordinate
145 faces
= [f
for f
in bm
.faces
if f
.select
]
148 uvs
= [l
[uv_layer
].uv
.copy() for l
in f
.loops
]
149 uv_list
[obj
].append(uvs
)
154 fill_holes
=self
.fill_holes
,
155 correct_aspect
=self
.correct_aspect
,
156 use_subsurf_data
=self
.use_subsurf_data
,
159 # when U/V-Constraint is checked, revert original coordinate
161 bm
= bmesh
.from_edit_mesh(obj
.data
)
162 if common
.check_version(2, 73, 0) >= 0:
163 bm
.faces
.ensure_lookup_table()
164 uv_layer
= bm
.loops
.layers
.uv
.verify()
165 faces
= [f
for f
in bm
.faces
if f
.select
]
167 for f
, uvs
in zip(faces
, uv_list
[obj
]):
168 for l
, uv
in zip(f
.loops
, uvs
):
170 l
[uv_layer
].uv
.x
= uv
.x
172 l
[uv_layer
].uv
.y
= uv
.y
175 bmesh
.update_edit_mesh(obj
.data
)