1 # SPDX-FileCopyrightText: 2018-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 mathutils
import Vector
12 from bpy
.props
import EnumProperty
, BoolProperty
, FloatVectorProperty
16 from ..utils
.bl_class_registry
import BlClassRegistry
17 from ..utils
.property_class_registry
import PropertyClassRegistry
18 from ..utils
import compatibility
as compat
21 def _is_valid_context(context
):
22 # 'IMAGE_EDITOR' and 'VIEW_3D' space is allowed to execute.
23 # If 'View_3D' space is not allowed, you can't find option in Tool-Shelf
25 if not common
.is_valid_space(context
, ['IMAGE_EDITOR', 'VIEW_3D']):
31 @PropertyClassRegistry()
33 idname
= "align_uv_cursor"
36 def init_props(cls
, scene
):
37 def auvc_get_cursor_loc(self
):
38 area
, _
, space
= common
.get_space('IMAGE_EDITOR', 'WINDOW',
40 if compat
.check_version(2, 80, 0) < 0:
41 bd_size
= common
.get_uvimg_editor_board_size(area
)
44 loc
= space
.cursor_location
46 if bd_size
[0] < 0.000001:
49 cx
= loc
[0] / bd_size
[0]
50 if bd_size
[1] < 0.000001:
53 cy
= loc
[1] / bd_size
[1]
55 self
['muv_align_uv_cursor_cursor_loc'] = Vector((cx
, cy
))
56 return self
.get('muv_align_uv_cursor_cursor_loc', (0.0, 0.0))
58 def auvc_set_cursor_loc(self
, value
):
59 self
['muv_align_uv_cursor_cursor_loc'] = value
60 area
, _
, space
= common
.get_space('IMAGE_EDITOR', 'WINDOW',
62 if compat
.check_version(2, 80, 0) < 0:
63 bd_size
= common
.get_uvimg_editor_board_size(area
)
66 cx
= bd_size
[0] * value
[0]
67 cy
= bd_size
[1] * value
[1]
68 space
.cursor_location
= Vector((cx
, cy
))
70 scene
.muv_align_uv_cursor_enabled
= BoolProperty(
71 name
="Align UV Cursor Enabled",
72 description
="Align UV Cursor is enabled",
76 scene
.muv_align_uv_cursor_cursor_loc
= FloatVectorProperty(
77 name
="UV Cursor Location",
83 default
=(0.000, 0.000),
84 get
=auvc_get_cursor_loc
,
85 set=auvc_set_cursor_loc
87 scene
.muv_align_uv_cursor_align_method
= EnumProperty(
89 description
="Align Method",
92 ('TEXTURE', "Texture", "Align to texture"),
93 ('UV', "UV", "Align to UV"),
94 ('UV_SEL', "UV (Selected)", "Align to Selected UV")
98 scene
.muv_uv_cursor_location_enabled
= BoolProperty(
99 name
="UV Cursor Location Enabled",
100 description
="UV Cursor Location is enabled",
105 def del_props(cls
, scene
):
106 del scene
.muv_align_uv_cursor_enabled
107 del scene
.muv_align_uv_cursor_cursor_loc
108 del scene
.muv_align_uv_cursor_align_method
110 del scene
.muv_uv_cursor_location_enabled
114 @compat.make_annotations
115 class MUV_OT_AlignUVCursor(bpy
.types
.Operator
):
117 bl_idname
= "uv.muv_align_uv_cursor"
118 bl_label
= "Align UV Cursor"
119 bl_description
= "Align cursor to the center of UV island"
120 bl_options
= {'REGISTER', 'UNDO'}
122 position
= EnumProperty(
124 ('CENTER', "Center", "Align to Center"),
125 ('LEFT_TOP', "Left Top", "Align to Left Top"),
126 ('LEFT_MIDDLE', "Left Middle", "Align to Left Middle"),
127 ('LEFT_BOTTOM', "Left Bottom", "Align to Left Bottom"),
128 ('MIDDLE_TOP', "Middle Top", "Align to Middle Top"),
129 ('MIDDLE_BOTTOM', "Middle Bottom", "Align to Middle Bottom"),
130 ('RIGHT_TOP', "Right Top", "Align to Right Top"),
131 ('RIGHT_MIDDLE', "Right Middle", "Align to Right Middle"),
132 ('RIGHT_BOTTOM', "Right Bottom", "Align to Right Bottom")
135 description
="Align position",
140 ('TEXTURE', "Texture", "Align based on Texture"),
141 ('UV', "UV", "Align to UV"),
142 ('UV_SEL', "UV (Selected)", "Align to Selected UV")
145 description
="Align base",
150 def poll(cls
, context
):
151 # we can not get area/space/region from console
152 if common
.is_console_mode():
154 return _is_valid_context(context
)
156 def execute(self
, context
):
157 area
, _
, space
= common
.get_space('IMAGE_EDITOR', 'WINDOW',
159 if compat
.check_version(2, 80, 0) < 0:
160 bd_size
= common
.get_uvimg_editor_board_size(area
)
165 if self
.base
== 'UV':
166 objs
= common
.get_uv_editable_objects(context
)
167 no_selected_face
= True
169 max_
= Vector((-large_value
, -large_value
))
170 min_
= Vector((large_value
, large_value
))
172 bm
= bmesh
.from_edit_mesh(obj
.data
)
173 if not bm
.loops
.layers
.uv
:
175 uv_layer
= bm
.loops
.layers
.uv
.verify()
178 if (not context
.tool_settings
.use_uv_select_sync
and
183 max_
.x
= max(max_
.x
, uv
.x
)
184 max_
.y
= max(max_
.y
, uv
.y
)
185 min_
.x
= min(min_
.x
, uv
.x
)
186 min_
.y
= min(min_
.y
, uv
.y
)
187 no_selected_face
= False
189 max_
= Vector((1.0, 1.0))
190 min_
= Vector((0.0, 0.0))
192 (max_
.x
+ min_
.x
) / 2.0, (max_
.y
+ min_
.y
) / 2.0
195 # pylint: disable=R1702
196 elif self
.base
== 'UV_SEL':
197 objs
= common
.get_uv_editable_objects(context
)
198 no_selected_face
= True
200 max_
= Vector((-large_value
, -large_value
))
201 min_
= Vector((large_value
, large_value
))
203 bm
= bmesh
.from_edit_mesh(obj
.data
)
204 if not bm
.loops
.layers
.uv
:
206 uv_layer
= bm
.loops
.layers
.uv
.verify()
208 if context
.tool_settings
.use_uv_select_sync
:
212 for l
in v
.link_loops
:
214 max_
.x
= max(max_
.x
, uv
.x
)
215 max_
.y
= max(max_
.y
, uv
.y
)
216 min_
.x
= min(min_
.x
, uv
.x
)
217 min_
.y
= min(min_
.y
, uv
.y
)
218 no_selected_face
= False
224 if not l
[uv_layer
].select
:
227 max_
.x
= max(max_
.x
, uv
.x
)
228 max_
.y
= max(max_
.y
, uv
.y
)
229 min_
.x
= min(min_
.x
, uv
.x
)
230 min_
.y
= min(min_
.y
, uv
.y
)
231 no_selected_face
= False
233 max_
= Vector((1.0, 1.0))
234 min_
= Vector((0.0, 0.0))
236 (max_
.x
+ min_
.x
) / 2.0, (max_
.y
+ min_
.y
) / 2.0
239 elif self
.base
== 'TEXTURE':
240 min_
= Vector((0.0, 0.0))
241 max_
= Vector((1.0, 1.0))
242 center
= Vector((0.5, 0.5))
244 self
.report({'ERROR'}, "Unknown Operation")
247 if self
.position
== 'CENTER':
250 elif self
.position
== 'LEFT_TOP':
253 elif self
.position
== 'LEFT_MIDDLE':
256 elif self
.position
== 'LEFT_BOTTOM':
259 elif self
.position
== 'MIDDLE_TOP':
262 elif self
.position
== 'MIDDLE_BOTTOM':
265 elif self
.position
== 'RIGHT_TOP':
268 elif self
.position
== 'RIGHT_MIDDLE':
271 elif self
.position
== 'RIGHT_BOTTOM':
275 self
.report({'ERROR'}, "Unknown Operation")
281 space
.cursor_location
= Vector((cx
, cy
))