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__
= "31 Jul 2019"
27 from bpy
.props
import (
33 from bpy
.types
import AddonPreferences
36 from .op
.flip_rotate_uv
import MUV_OT_FlipRotateUV
37 from .op
.mirror_uv
import MUV_OT_MirrorUV
38 from .op
.move_uv
import MUV_OT_MoveUV
39 from .op
.unwrap_constraint
import MUV_OT_UnwrapConstraint
40 from .op
.pack_uv
import MUV_OT_PackUV
41 from .op
.smooth_uv
import MUV_OT_SmoothUV
42 from .ui
.VIEW3D_MT_uv_map
import (
46 MUV_MT_PreserveUVAspect
,
49 MUV_MT_TextureProjection
,
52 from .ui
.VIEW3D_MT_object
import MUV_MT_CopyPasteUV_Object
53 from .ui
.IMAGE_MT_uvs
import (
54 MUV_MT_CopyPasteUV_UVEdit
,
60 from .utils
.bl_class_registry
import BlClassRegistry
61 from .utils
.addon_updater
import AddonUpdaterManager
62 from .utils
import compatibility
as compat
66 def view3d_uvmap_menu_fn(self
, context
):
71 layout
.label(text
="Copy/Paste UV", icon
=compat
.icon('IMAGE'))
73 layout
.menu(MUV_MT_CopyPasteUV
.bl_idname
, text
="Copy/Paste UV")
75 layout
.menu(MUV_MT_TransferUV
.bl_idname
, text
="Transfer UV")
78 layout
.label(text
="UV Manipulation", icon
=compat
.icon('IMAGE'))
80 ops
= layout
.operator(MUV_OT_FlipRotateUV
.bl_idname
, text
="Flip/Rotate UV")
81 ops
.seams
= sc
.muv_flip_rotate_uv_seams
83 ops
= layout
.operator(MUV_OT_MirrorUV
.bl_idname
, text
="Mirror UV")
84 ops
.axis
= sc
.muv_mirror_uv_axis
86 layout
.operator(MUV_OT_MoveUV
.bl_idname
, text
="Move UV")
88 layout
.menu(MUV_MT_WorldScaleUV
.bl_idname
, text
="World Scale UV")
90 layout
.menu(MUV_MT_PreserveUVAspect
.bl_idname
, text
="Preserve UV")
92 layout
.menu(MUV_MT_TextureLock
.bl_idname
, text
="Texture Lock")
94 layout
.menu(MUV_MT_TextureWrap
.bl_idname
, text
="Texture Wrap")
96 layout
.prop(sc
, "muv_uv_sculpt_enable", text
="UV Sculpt")
99 layout
.label(text
="UV Mapping", icon
=compat
.icon('IMAGE'))
101 ops
= layout
.operator(MUV_OT_UnwrapConstraint
.bl_idname
,
102 text
="Unwrap Constraint")
103 ops
.u_const
= sc
.muv_unwrap_constraint_u_const
104 ops
.v_const
= sc
.muv_unwrap_constraint_v_const
106 layout
.menu(MUV_MT_TextureProjection
.bl_idname
, text
="Texture Projection")
108 layout
.menu(MUV_MT_UVW
.bl_idname
, text
="UVW")
111 def view3d_object_menu_fn(self
, _
):
115 layout
.label(text
="Copy/Paste UV", icon
=compat
.icon('IMAGE'))
116 # Copy/Paste UV (Among Object)
117 layout
.menu(MUV_MT_CopyPasteUV_Object
.bl_idname
, text
="Copy/Paste UV")
120 def image_uvs_menu_fn(self
, context
):
125 # Copy/Paste UV (on UV/Image Editor)
126 layout
.label(text
="Copy/Paste UV", icon
=compat
.icon('IMAGE'))
127 layout
.menu(MUV_MT_CopyPasteUV_UVEdit
.bl_idname
, text
="Copy/Paste UV")
131 layout
.label(text
="UV Manipulation", icon
=compat
.icon('IMAGE'))
132 ops
= layout
.operator(MUV_OT_PackUV
.bl_idname
, text
="Pack UV")
133 ops
.allowable_center_deviation
= sc
.muv_pack_uv_allowable_center_deviation
134 ops
.allowable_size_deviation
= sc
.muv_pack_uv_allowable_size_deviation
136 layout
.menu(MUV_MT_SelectUV
.bl_idname
, text
="Select UV")
138 ops
= layout
.operator(MUV_OT_SmoothUV
.bl_idname
, text
="Smooth")
139 ops
.transmission
= sc
.muv_smooth_uv_transmission
140 ops
.select
= sc
.muv_smooth_uv_select
141 ops
.mesh_infl
= sc
.muv_smooth_uv_mesh_infl
143 layout
.menu(MUV_MT_AlignUV
.bl_idname
, text
="Align UV")
147 layout
.label(text
="Editor Enhancement", icon
=compat
.icon('IMAGE'))
148 layout
.menu(MUV_MT_AlignUVCursor
.bl_idname
, text
="Align UV Cursor")
150 layout
.prop(sc
, "muv_uv_bounding_box_show", text
="UV Bounding Box")
152 layout
.menu(MUV_MT_UVInspection
.bl_idname
, text
="UV Inspection")
155 def add_builtin_menu():
156 bpy
.types
.VIEW3D_MT_uv_map
.append(view3d_uvmap_menu_fn
)
157 bpy
.types
.VIEW3D_MT_object
.append(view3d_object_menu_fn
)
158 bpy
.types
.IMAGE_MT_uvs
.append(image_uvs_menu_fn
)
161 def remove_builtin_menu():
162 bpy
.types
.IMAGE_MT_uvs
.remove(image_uvs_menu_fn
)
163 bpy
.types
.VIEW3D_MT_object
.remove(view3d_object_menu_fn
)
164 bpy
.types
.VIEW3D_MT_uv_map
.remove(view3d_uvmap_menu_fn
)
167 def get_update_candidate_branches(_
, __
):
168 manager
= AddonUpdaterManager
.get_instance()
169 if not manager
.candidate_checked():
172 return [(name
, name
, "") for name
in manager
.get_candidate_branch_names()]
175 def set_debug_mode(self
, value
):
176 self
['enable_debug_mode'] = value
179 def get_debug_mode(self
):
180 enabled
= self
.get('enable_debug_mode', False)
182 common
.enable_debugg_mode()
184 common
.disable_debug_mode()
189 @compat.make_annotations
190 class MUV_Preferences(AddonPreferences
):
191 """Preferences class: Preferences for this add-on"""
193 bl_idname
= "magic_uv"
195 def update_enable_builtin_menu(self
, _
):
196 if self
['enable_builtin_menu']:
199 remove_builtin_menu()
201 # enable to add features to built-in menu
202 enable_builtin_menu
= BoolProperty(
203 name
="Built-in Menu",
204 description
="Enable built-in menu",
206 update
=update_enable_builtin_menu
,
210 enable_debug_mode
= BoolProperty(
212 description
="Enable debugging mode",
219 uv_sculpt_brush_color
= FloatVectorProperty(
222 default
=(1.0, 0.4, 0.4, 1.0),
230 uv_inspection_overlapped_color
= FloatVectorProperty(
233 default
=(0.0, 0.0, 1.0, 0.3),
241 uv_inspection_flipped_color
= FloatVectorProperty(
244 default
=(1.0, 0.0, 0.0, 0.3),
251 # for Texture Projection
252 texture_projection_canvas_padding
= FloatVectorProperty(
253 name
="Canvas Padding",
254 description
="Canvas Padding",
258 default
=(20.0, 20.0))
260 # for UV Bounding Box
261 uv_bounding_box_cp_size
= FloatProperty(
263 description
="Control Point Size",
267 uv_bounding_box_cp_react_size
= FloatProperty(
269 description
="Size event fired",
275 category
= EnumProperty(
277 description
="Preferences Category",
279 ('INFO', "Information", "Information about this add-on"),
280 ('CONFIG', "Configuration", "Configuration about this add-on"),
281 ('UPDATE', "Update", "Update this add-on"),
285 info_desc_expanded
= BoolProperty(
287 description
="Description",
290 info_loc_expanded
= BoolProperty(
292 description
="Location",
295 conf_uv_sculpt_expanded
= BoolProperty(
297 description
="UV Sculpt",
300 conf_uv_inspection_expanded
= BoolProperty(
301 name
="UV Inspection",
302 description
="UV Inspection",
305 conf_texture_projection_expanded
= BoolProperty(
306 name
="Texture Projection",
307 description
="Texture Projection",
310 conf_uv_bounding_box_expanded
= BoolProperty(
311 name
="UV Bounding Box",
312 description
="UV Bounding Box",
317 updater_branch_to_update
= EnumProperty(
319 description
="Target branch to update add-on",
320 items
=get_update_candidate_branches
326 layout
.row().prop(self
, "category", expand
=True)
328 if self
.category
== 'INFO':
332 self
, "info_desc_expanded", text
="Description",
333 icon
='DISCLOSURE_TRI_DOWN' if self
.info_desc_expanded
334 else 'DISCLOSURE_TRI_RIGHT')
335 if self
.info_desc_expanded
:
336 col
= layout
.column(align
=True)
337 col
.label(text
="Magic UV is composed of many UV editing" +
339 col
.label(text
="See tutorial page if you are new to this" +
341 col
.label(text
="https://github.com/nutti/Magic-UV" +
345 self
, "info_loc_expanded", text
="Location",
346 icon
='DISCLOSURE_TRI_DOWN' if self
.info_loc_expanded
347 else 'DISCLOSURE_TRI_RIGHT')
348 if self
.info_loc_expanded
:
349 row
= layout
.row(align
=True)
350 sp
= compat
.layout_split(row
, 0.5)
351 sp
.label(text
="3D View > Sidebar > " +
352 "Copy/Paste UV (Object mode)")
353 sp
= compat
.layout_split(sp
, 1.0)
354 col
= sp
.column(align
=True)
355 col
.label(text
="Copy/Paste UV (Among objects)")
357 row
= layout
.row(align
=True)
358 sp
= compat
.layout_split(row
, 0.5)
359 sp
.label(text
="3D View > Sidebar > " +
360 "Copy/Paste UV (Edit mode)")
361 sp
= compat
.layout_split(sp
, 1.0)
362 col
= sp
.column(align
=True)
363 col
.label(text
="Copy/Paste UV (Among faces in 3D View)")
364 col
.label(text
="Transfer UV")
366 row
= layout
.row(align
=True)
367 sp
= compat
.layout_split(row
, 0.5)
368 sp
.label(text
="3D View > Sidebar > " +
369 "UV Manipulation (Edit mode)")
370 sp
= compat
.layout_split(sp
, 1.0)
371 col
= sp
.column(align
=True)
372 col
.label(text
="Flip/Rotate UV")
373 col
.label(text
="Mirror UV")
374 col
.label(text
="Move UV")
375 col
.label(text
="World Scale UV")
376 col
.label(text
="Preserve UV Aspect")
377 col
.label(text
="Texture Lock")
378 col
.label(text
="Texture Wrap")
379 col
.label(text
="UV Sculpt")
381 row
= layout
.row(align
=True)
382 sp
= compat
.layout_split(row
, 0.5)
383 sp
.label(text
="3D View > Sidebar > " +
384 "UV Manipulation (Edit mode)")
385 sp
= compat
.layout_split(sp
, 1.0)
386 col
= sp
.column(align
=True)
387 col
.label(text
="Unwrap Constraint")
388 col
.label(text
="Texture Projection")
389 col
.label(text
="UVW")
391 row
= layout
.row(align
=True)
392 sp
= compat
.layout_split(row
, 0.5)
393 sp
.label(text
="UV/Image Editor > Sidebar > Copy/Paste UV")
394 sp
= compat
.layout_split(sp
, 1.0)
395 col
= sp
.column(align
=True)
396 col
.label(text
="Copy/Paste UV " +
397 "(Among faces in UV/Image Editor)")
399 row
= layout
.row(align
=True)
400 sp
= compat
.layout_split(row
, 0.5)
401 sp
.label(text
="UV/Image Editor > Sidebar > UV Manipulation")
402 sp
= compat
.layout_split(sp
, 1.0)
403 col
= sp
.column(align
=True)
404 col
.label(text
="Align UV")
405 col
.label(text
="Smooth UV")
406 col
.label(text
="Select UV")
407 col
.label(text
="Pack UV (Extension)")
409 row
= layout
.row(align
=True)
410 sp
= compat
.layout_split(row
, 0.5)
411 sp
.label(text
="UV/Image Editor > Sidebar > " +
412 "Editor Enhancement")
413 sp
= compat
.layout_split(sp
, 1.0)
414 col
= sp
.column(align
=True)
415 col
.label(text
="Align UV Cursor")
416 col
.label(text
="UV Cursor Location")
417 col
.label(text
="UV Bounding Box")
418 col
.label(text
="UV Inspection")
420 elif self
.category
== 'CONFIG':
423 layout
.prop(self
, "enable_builtin_menu", text
="Built-in Menu")
424 layout
.prop(self
, "enable_debug_mode", text
="Debug Mode")
429 self
, "conf_uv_sculpt_expanded", text
="UV Sculpt",
430 icon
='DISCLOSURE_TRI_DOWN' if self
.conf_uv_sculpt_expanded
431 else 'DISCLOSURE_TRI_RIGHT')
432 if self
.conf_uv_sculpt_expanded
:
433 sp
= compat
.layout_split(layout
, 0.05)
434 col
= sp
.column() # spacer
435 sp
= compat
.layout_split(sp
, 0.3)
437 col
.label(text
="Brush Color:")
438 col
.prop(self
, "uv_sculpt_brush_color", text
="")
442 self
, "conf_uv_inspection_expanded", text
="UV Inspection",
443 icon
='DISCLOSURE_TRI_DOWN' if self
.conf_uv_inspection_expanded
444 else 'DISCLOSURE_TRI_RIGHT')
445 if self
.conf_uv_inspection_expanded
:
446 sp
= compat
.layout_split(layout
, 0.05)
447 col
= sp
.column() # spacer
448 sp
= compat
.layout_split(sp
, 0.3)
450 col
.label(text
="Overlapped UV Color:")
451 col
.prop(self
, "uv_inspection_overlapped_color", text
="")
452 sp
= compat
.layout_split(sp
, 0.45)
454 col
.label(text
="Flipped UV Color:")
455 col
.prop(self
, "uv_inspection_flipped_color", text
="")
459 self
, "conf_texture_projection_expanded",
460 text
="Texture Projection",
461 icon
='DISCLOSURE_TRI_DOWN'
462 if self
.conf_texture_projection_expanded
463 else 'DISCLOSURE_TRI_RIGHT')
464 if self
.conf_texture_projection_expanded
:
465 sp
= compat
.layout_split(layout
, 0.05)
466 col
= sp
.column() # spacer
467 sp
= compat
.layout_split(sp
, 0.3)
469 col
.prop(self
, "texture_projection_canvas_padding")
473 self
, "conf_uv_bounding_box_expanded", text
="UV Bounding Box",
474 icon
='DISCLOSURE_TRI_DOWN'
475 if self
.conf_uv_bounding_box_expanded
476 else 'DISCLOSURE_TRI_RIGHT')
477 if self
.conf_uv_bounding_box_expanded
:
478 sp
= compat
.layout_split(layout
, 0.05)
479 col
= sp
.column() # spacer
480 sp
= compat
.layout_split(sp
, 0.3)
482 col
.label(text
="Control Point:")
483 col
.prop(self
, "uv_bounding_box_cp_size")
484 col
.prop(self
, "uv_bounding_box_cp_react_size")
487 elif self
.category
== 'UPDATE':
488 updater
.draw_updater_ui(self
)