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"
8 __date__
= "22 Apr 2022"
11 from bpy
.props
import (
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']):
29 objs
= common
.get_uv_editable_objects(context
)
33 # only edit mode is allowed to execute
34 if context
.object.mode
!= 'EDIT':
40 @PropertyClassRegistry()
42 idname
= "unwrap_constraint"
45 def init_props(cls
, scene
):
46 scene
.muv_unwrap_constraint_enabled
= BoolProperty(
47 name
="Unwrap Constraint Enabled",
48 description
="Unwrap Constraint is enabled",
51 scene
.muv_unwrap_constraint_u_const
= BoolProperty(
53 description
="Keep UV U-axis coordinate",
56 scene
.muv_unwrap_constraint_v_const
= BoolProperty(
58 description
="Keep UV V-axis coordinate",
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
):
73 Operation class: Unwrap with constrain UV coordinate
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(
84 description
="Unwrapping method",
86 ('ANGLE_BASED', 'Angle Based', 'Angle Based'),
87 ('CONFORMAL', 'Conformal', 'Conformal')
89 default
='ANGLE_BASED')
90 fill_holes
= BoolProperty(
92 description
="Virtual fill holes in meshes before unwrapping",
94 correct_aspect
= BoolProperty(
95 name
="Correct Aspect",
96 description
="Map UVs taking image aspect ratio into account",
98 use_subsurf_data
= BoolProperty(
99 name
="Use Subsurf Modifier",
100 description
="""Map UVs taking vertex position after subsurf
103 margin
= FloatProperty(
105 description
="Space between islands",
110 # property for this operation
111 u_const
= BoolProperty(
113 description
="Keep UV U-axis coordinate",
116 v_const
= BoolProperty(
118 description
="Keep UV V-axis coordinate",
123 def poll(cls
, context
):
124 # we can not get area/space/region from console
125 if common
.is_console_mode():
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 }
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"
144 uv_layer
= bm
.loops
.layers
.uv
.verify()
146 # get original UV coordinate
147 faces
= [f
for f
in bm
.faces
if f
.select
]
150 uvs
= [l
[uv_layer
].uv
.copy() for l
in f
.loops
]
151 uv_list
[obj
].append(uvs
)
156 fill_holes
=self
.fill_holes
,
157 correct_aspect
=self
.correct_aspect
,
158 use_subsurf_data
=self
.use_subsurf_data
,
161 # when U/V-Constraint is checked, revert original coordinate
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
):
172 l
[uv_layer
].uv
.x
= uv
.x
174 l
[uv_layer
].uv
.y
= uv
.y
177 bmesh
.update_edit_mesh(obj
.data
)