3 # ##### BEGIN GPL LICENSE BLOCK #####
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software Foundation,
17 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 # ##### END GPL LICENSE BLOCK #####
21 __author__
= "Nutti <nutti.metro@gmail.com>"
22 __status__
= "production"
24 __date__
= "6 Mar 2021"
27 from bpy
.props
import (
33 from bpy
.types
import AddonPreferences
36 from .op
.clip_uv
import MUV_OT_ClipUV
37 from .op
.flip_rotate_uv
import MUV_OT_FlipRotateUV
38 from .op
.mirror_uv
import MUV_OT_MirrorUV
39 from .op
.move_uv
import MUV_OT_MoveUV
40 from .op
.unwrap_constraint
import MUV_OT_UnwrapConstraint
41 from .op
.pack_uv
import MUV_OT_PackUV
42 from .op
.smooth_uv
import MUV_OT_SmoothUV
43 from .ui
.VIEW3D_MT_uv_map
import (
47 MUV_MT_PreserveUVAspect
,
50 MUV_MT_TextureProjection
,
53 from .ui
.VIEW3D_MT_object
import MUV_MT_CopyPasteUV_Object
54 from .ui
.IMAGE_MT_uvs
import (
55 MUV_MT_CopyPasteUV_UVEdit
,
61 from .utils
.bl_class_registry
import BlClassRegistry
62 from .utils
import compatibility
as compat
65 def view3d_uvmap_menu_fn(self
, context
):
70 layout
.label(text
="Copy/Paste UV", icon
=compat
.icon('IMAGE'))
72 layout
.menu(MUV_MT_CopyPasteUV
.bl_idname
, text
="Copy/Paste UV")
74 layout
.menu(MUV_MT_TransferUV
.bl_idname
, text
="Transfer UV")
77 layout
.label(text
="UV Manipulation", icon
=compat
.icon('IMAGE'))
79 ops
= layout
.operator(MUV_OT_FlipRotateUV
.bl_idname
, text
="Flip/Rotate UV")
80 ops
.seams
= sc
.muv_flip_rotate_uv_seams
82 ops
= layout
.operator(MUV_OT_MirrorUV
.bl_idname
, text
="Mirror UV")
83 ops
.axis
= sc
.muv_mirror_uv_axis
85 layout
.operator(MUV_OT_MoveUV
.bl_idname
, text
="Move UV")
87 layout
.menu(MUV_MT_WorldScaleUV
.bl_idname
, text
="World Scale UV")
89 layout
.menu(MUV_MT_PreserveUVAspect
.bl_idname
, text
="Preserve UV")
91 layout
.menu(MUV_MT_TextureLock
.bl_idname
, text
="Texture Lock")
93 layout
.menu(MUV_MT_TextureWrap
.bl_idname
, text
="Texture Wrap")
95 layout
.prop(sc
, "muv_uv_sculpt_enable", text
="UV Sculpt")
98 layout
.label(text
="UV Mapping", icon
=compat
.icon('IMAGE'))
100 ops
= layout
.operator(MUV_OT_UnwrapConstraint
.bl_idname
,
101 text
="Unwrap Constraint")
102 ops
.u_const
= sc
.muv_unwrap_constraint_u_const
103 ops
.v_const
= sc
.muv_unwrap_constraint_v_const
105 layout
.menu(MUV_MT_TextureProjection
.bl_idname
, text
="Texture Projection")
107 layout
.menu(MUV_MT_UVW
.bl_idname
, text
="UVW")
110 def view3d_object_menu_fn(self
, _
):
114 layout
.label(text
="Copy/Paste UV", icon
=compat
.icon('IMAGE'))
115 # Copy/Paste UV (Among Object)
116 layout
.menu(MUV_MT_CopyPasteUV_Object
.bl_idname
, text
="Copy/Paste UV")
119 def image_uvs_menu_fn(self
, context
):
124 layout
.label(text
="Copy/Paste UV", icon
=compat
.icon('IMAGE'))
125 # Copy/Paste UV (on UV/Image Editor)
126 layout
.menu(MUV_MT_CopyPasteUV_UVEdit
.bl_idname
, text
="Copy/Paste UV")
129 layout
.label(text
="UV Manipulation", icon
=compat
.icon('IMAGE'))
131 ops
= layout
.operator(MUV_OT_ClipUV
.bl_idname
, text
="Clip UV")
132 ops
.clip_uv_range_max
= sc
.muv_clip_uv_range_max
133 ops
.clip_uv_range_min
= sc
.muv_clip_uv_range_min
135 ops
= layout
.operator(MUV_OT_PackUV
.bl_idname
, text
="Pack UV")
136 ops
.allowable_center_deviation
= sc
.muv_pack_uv_allowable_center_deviation
137 ops
.allowable_size_deviation
= sc
.muv_pack_uv_allowable_size_deviation
139 layout
.menu(MUV_MT_SelectUV
.bl_idname
, text
="Select UV")
141 ops
= layout
.operator(MUV_OT_SmoothUV
.bl_idname
, text
="Smooth")
142 ops
.transmission
= sc
.muv_smooth_uv_transmission
143 ops
.select
= sc
.muv_smooth_uv_select
144 ops
.mesh_infl
= sc
.muv_smooth_uv_mesh_infl
146 layout
.menu(MUV_MT_AlignUV
.bl_idname
, text
="Align UV")
149 layout
.label(text
="Editor Enhancement", icon
=compat
.icon('IMAGE'))
151 layout
.menu(MUV_MT_AlignUVCursor
.bl_idname
, text
="Align UV Cursor")
153 layout
.prop(sc
, "muv_uv_bounding_box_show", text
="UV Bounding Box")
155 layout
.menu(MUV_MT_UVInspection
.bl_idname
, text
="UV Inspection")
158 def add_builtin_menu():
159 bpy
.types
.VIEW3D_MT_uv_map
.append(view3d_uvmap_menu_fn
)
160 bpy
.types
.VIEW3D_MT_object
.append(view3d_object_menu_fn
)
161 bpy
.types
.IMAGE_MT_uvs
.append(image_uvs_menu_fn
)
164 def remove_builtin_menu():
165 bpy
.types
.IMAGE_MT_uvs
.remove(image_uvs_menu_fn
)
166 bpy
.types
.VIEW3D_MT_object
.remove(view3d_object_menu_fn
)
167 bpy
.types
.VIEW3D_MT_uv_map
.remove(view3d_uvmap_menu_fn
)
170 def set_debug_mode(self
, value
):
171 self
['enable_debug_mode'] = value
174 def get_debug_mode(self
):
175 enabled
= self
.get('enable_debug_mode', False)
177 common
.enable_debugg_mode()
179 common
.disable_debug_mode()
184 @compat.make_annotations
185 class MUV_Preferences(AddonPreferences
):
186 """Preferences class: Preferences for this add-on"""
188 bl_idname
= "magic_uv"
190 def update_enable_builtin_menu(self
, _
):
191 if self
['enable_builtin_menu']:
194 remove_builtin_menu()
196 # enable to add features to built-in menu
197 enable_builtin_menu
= BoolProperty(
198 name
="Built-in Menu",
199 description
="Enable built-in menu",
201 update
=update_enable_builtin_menu
,
205 enable_debug_mode
= BoolProperty(
207 description
="Enable debugging mode",
214 uv_sculpt_brush_color
= FloatVectorProperty(
217 default
=(1.0, 0.4, 0.4, 1.0),
225 uv_inspection_overlapped_color
= FloatVectorProperty(
228 default
=(0.0, 0.0, 1.0, 0.3),
234 uv_inspection_overlapped_color_for_v3d
= FloatVectorProperty(
235 name
="Color (View3D)",
236 description
="Color in View3D",
237 default
=(0.0, 0.0, 1.0, 0.5),
245 uv_inspection_flipped_color
= FloatVectorProperty(
248 default
=(1.0, 0.0, 0.0, 0.3),
254 uv_inspection_flipped_color_for_v3d
= FloatVectorProperty(
255 name
="Color (View3D)",
256 description
="Color in View3D",
257 default
=(1.0, 0.0, 0.0, 0.5),
264 # for Texture Projection
265 texture_projection_canvas_padding
= FloatVectorProperty(
266 name
="Canvas Padding",
267 description
="Canvas Padding",
271 default
=(20.0, 20.0))
273 # for UV Bounding Box
274 uv_bounding_box_cp_size
= FloatProperty(
276 description
="Control Point Size",
280 uv_bounding_box_cp_react_size
= FloatProperty(
282 description
="Size event fired",
288 category
= EnumProperty(
290 description
="Preferences Category",
292 ('INFO', "Information", "Information about this add-on"),
293 ('CONFIG', "Configuration", "Configuration about this add-on"),
297 info_desc_expanded
= BoolProperty(
299 description
="Description",
302 info_loc_expanded
= BoolProperty(
304 description
="Location",
307 conf_uv_sculpt_expanded
= BoolProperty(
309 description
="UV Sculpt",
312 conf_uv_inspection_expanded
= BoolProperty(
313 name
="UV Inspection",
314 description
="UV Inspection",
317 conf_texture_projection_expanded
= BoolProperty(
318 name
="Texture Projection",
319 description
="Texture Projection",
322 conf_uv_bounding_box_expanded
= BoolProperty(
323 name
="UV Bounding Box",
324 description
="UV Bounding Box",
331 layout
.row().prop(self
, "category", expand
=True)
333 if self
.category
== 'INFO':
337 self
, "info_desc_expanded", text
="Description",
338 icon
='DISCLOSURE_TRI_DOWN' if self
.info_desc_expanded
339 else 'DISCLOSURE_TRI_RIGHT')
340 if self
.info_desc_expanded
:
341 col
= layout
.column(align
=True)
342 col
.label(text
="Magic UV is composed of many UV editing" +
344 col
.label(text
="See tutorial page if you are new to this" +
346 col
.label(text
="https://github.com/nutti/Magic-UV" +
350 self
, "info_loc_expanded", text
="Location",
351 icon
='DISCLOSURE_TRI_DOWN' if self
.info_loc_expanded
352 else 'DISCLOSURE_TRI_RIGHT')
353 if self
.info_loc_expanded
:
354 row
= layout
.row(align
=True)
355 sp
= compat
.layout_split(row
, 0.5)
356 sp
.label(text
="3D View > Sidebar > " +
357 "Copy/Paste UV (Object mode)")
358 sp
= compat
.layout_split(sp
, 1.0)
359 col
= sp
.column(align
=True)
360 col
.label(text
="Copy/Paste UV (Among objects)")
362 row
= layout
.row(align
=True)
363 sp
= compat
.layout_split(row
, 0.5)
364 sp
.label(text
="3D View > Sidebar > " +
365 "Copy/Paste UV (Edit mode)")
366 sp
= compat
.layout_split(sp
, 1.0)
367 col
= sp
.column(align
=True)
368 col
.label(text
="Copy/Paste UV (Among faces in 3D View)")
369 col
.label(text
="Transfer UV")
371 row
= layout
.row(align
=True)
372 sp
= compat
.layout_split(row
, 0.5)
373 sp
.label(text
="3D View > Sidebar > " +
374 "UV Manipulation (Edit mode)")
375 sp
= compat
.layout_split(sp
, 1.0)
376 col
= sp
.column(align
=True)
377 col
.label(text
="Flip/Rotate UV")
378 col
.label(text
="Mirror UV")
379 col
.label(text
="Move UV")
380 col
.label(text
="World Scale UV")
381 col
.label(text
="Preserve UV Aspect")
382 col
.label(text
="Texture Lock")
383 col
.label(text
="Texture Wrap")
384 col
.label(text
="UV Sculpt")
386 row
= layout
.row(align
=True)
387 sp
= compat
.layout_split(row
, 0.5)
388 sp
.label(text
="3D View > Sidebar > " +
389 "UV Manipulation (Edit mode)")
390 sp
= compat
.layout_split(sp
, 1.0)
391 col
= sp
.column(align
=True)
392 col
.label(text
="Unwrap Constraint")
393 col
.label(text
="Texture Projection")
394 col
.label(text
="UVW")
396 row
= layout
.row(align
=True)
397 sp
= compat
.layout_split(row
, 0.5)
398 sp
.label(text
="UV/Image Editor > Sidebar > Copy/Paste UV")
399 sp
= compat
.layout_split(sp
, 1.0)
400 col
= sp
.column(align
=True)
401 col
.label(text
="Copy/Paste UV " +
402 "(Among faces in UV/Image Editor)")
404 row
= layout
.row(align
=True)
405 sp
= compat
.layout_split(row
, 0.5)
406 sp
.label(text
="UV/Image Editor > Sidebar > UV Manipulation")
407 sp
= compat
.layout_split(sp
, 1.0)
408 col
= sp
.column(align
=True)
409 col
.label(text
="Align UV")
410 col
.label(text
="Smooth UV")
411 col
.label(text
="Select UV")
412 col
.label(text
="Pack UV (Extension)")
414 row
= layout
.row(align
=True)
415 sp
= compat
.layout_split(row
, 0.5)
416 sp
.label(text
="UV/Image Editor > Sidebar > " +
417 "Editor Enhancement")
418 sp
= compat
.layout_split(sp
, 1.0)
419 col
= sp
.column(align
=True)
420 col
.label(text
="Align UV Cursor")
421 col
.label(text
="UV Cursor Location")
422 col
.label(text
="UV Bounding Box")
423 col
.label(text
="UV Inspection")
425 elif self
.category
== 'CONFIG':
428 layout
.prop(self
, "enable_builtin_menu", text
="Built-in Menu")
429 layout
.prop(self
, "enable_debug_mode", text
="Debug Mode")
434 self
, "conf_uv_sculpt_expanded", text
="UV Sculpt",
435 icon
='DISCLOSURE_TRI_DOWN' if self
.conf_uv_sculpt_expanded
436 else 'DISCLOSURE_TRI_RIGHT')
437 if self
.conf_uv_sculpt_expanded
:
438 sp
= compat
.layout_split(layout
, 0.05)
439 col
= sp
.column() # spacer
440 sp
= compat
.layout_split(sp
, 0.3)
442 col
.label(text
="Brush Color:")
443 col
.prop(self
, "uv_sculpt_brush_color", text
="")
447 self
, "conf_uv_inspection_expanded", text
="UV Inspection",
448 icon
='DISCLOSURE_TRI_DOWN' if self
.conf_uv_inspection_expanded
449 else 'DISCLOSURE_TRI_RIGHT')
450 if self
.conf_uv_inspection_expanded
:
451 sp
= compat
.layout_split(layout
, 0.05)
452 col
= sp
.column() # spacer
453 sp
= compat
.layout_split(sp
, 0.3)
455 col
.label(text
="Overlapped UV Color:")
456 col
.prop(self
, "uv_inspection_overlapped_color", text
="")
457 sp
= compat
.layout_split(sp
, 0.45)
459 col
.label(text
="Flipped UV Color:")
460 col
.prop(self
, "uv_inspection_flipped_color", text
="")
462 sp
= compat
.layout_split(layout
, 0.05)
463 col
= sp
.column() # spacer
464 sp
= compat
.layout_split(sp
, 0.3)
466 col
.label(text
="Overlapped UV Color (View3D):")
467 col
.prop(self
, "uv_inspection_overlapped_color_for_v3d",
469 sp
= compat
.layout_split(sp
, 0.45)
471 col
.label(text
="Flipped UV Color (View3D):")
472 col
.prop(self
, "uv_inspection_flipped_color_for_v3d",
478 self
, "conf_texture_projection_expanded",
479 text
="Texture Projection",
480 icon
='DISCLOSURE_TRI_DOWN'
481 if self
.conf_texture_projection_expanded
482 else 'DISCLOSURE_TRI_RIGHT')
483 if self
.conf_texture_projection_expanded
:
484 sp
= compat
.layout_split(layout
, 0.05)
485 col
= sp
.column() # spacer
486 sp
= compat
.layout_split(sp
, 0.3)
488 col
.prop(self
, "texture_projection_canvas_padding")
492 self
, "conf_uv_bounding_box_expanded", text
="UV Bounding Box",
493 icon
='DISCLOSURE_TRI_DOWN'
494 if self
.conf_uv_bounding_box_expanded
495 else 'DISCLOSURE_TRI_RIGHT')
496 if self
.conf_uv_bounding_box_expanded
:
497 sp
= compat
.layout_split(layout
, 0.05)
498 col
= sp
.column() # spacer
499 sp
= compat
.layout_split(sp
, 0.3)
501 col
.label(text
="Control Point:")
502 col
.prop(self
, "uv_bounding_box_cp_size")
503 col
.prop(self
, "uv_bounding_box_cp_react_size")