Cleanup: quiet character escape warnings
[blender-addons.git] / magic_uv / preferences.py
blob7d6ac95707176b4d3a739b6478b5939699633866
1 # <pep8-80 compliant>
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"
23 __version__ = "6.5"
24 __date__ = "6 Mar 2021"
26 import bpy
27 from bpy.props import (
28 FloatProperty,
29 FloatVectorProperty,
30 BoolProperty,
31 EnumProperty,
33 from bpy.types import AddonPreferences
35 from . import common
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 (
44 MUV_MT_CopyPasteUV,
45 MUV_MT_TransferUV,
46 MUV_MT_WorldScaleUV,
47 MUV_MT_PreserveUVAspect,
48 MUV_MT_TextureLock,
49 MUV_MT_TextureWrap,
50 MUV_MT_TextureProjection,
51 MUV_MT_UVW,
53 from .ui.VIEW3D_MT_object import MUV_MT_CopyPasteUV_Object
54 from .ui.IMAGE_MT_uvs import (
55 MUV_MT_CopyPasteUV_UVEdit,
56 MUV_MT_SelectUV,
57 MUV_MT_AlignUV,
58 MUV_MT_AlignUVCursor,
59 MUV_MT_UVInspection,
61 from .utils.bl_class_registry import BlClassRegistry
62 from .utils import compatibility as compat
65 def view3d_uvmap_menu_fn(self, context):
66 layout = self.layout
67 sc = context.scene
69 layout.separator()
70 layout.label(text="Copy/Paste UV", icon=compat.icon('IMAGE'))
71 # Copy/Paste UV
72 layout.menu(MUV_MT_CopyPasteUV.bl_idname, text="Copy/Paste UV")
73 # Transfer UV
74 layout.menu(MUV_MT_TransferUV.bl_idname, text="Transfer UV")
76 layout.separator()
77 layout.label(text="UV Manipulation", icon=compat.icon('IMAGE'))
78 # Flip/Rotate UV
79 ops = layout.operator(MUV_OT_FlipRotateUV.bl_idname, text="Flip/Rotate UV")
80 ops.seams = sc.muv_flip_rotate_uv_seams
81 # Mirror UV
82 ops = layout.operator(MUV_OT_MirrorUV.bl_idname, text="Mirror UV")
83 ops.axis = sc.muv_mirror_uv_axis
84 # Move UV
85 layout.operator(MUV_OT_MoveUV.bl_idname, text="Move UV")
86 # World Scale UV
87 layout.menu(MUV_MT_WorldScaleUV.bl_idname, text="World Scale UV")
88 # Preserve UV
89 layout.menu(MUV_MT_PreserveUVAspect.bl_idname, text="Preserve UV")
90 # Texture Lock
91 layout.menu(MUV_MT_TextureLock.bl_idname, text="Texture Lock")
92 # Texture Wrap
93 layout.menu(MUV_MT_TextureWrap.bl_idname, text="Texture Wrap")
94 # UV Sculpt
95 layout.prop(sc, "muv_uv_sculpt_enable", text="UV Sculpt")
97 layout.separator()
98 layout.label(text="UV Mapping", icon=compat.icon('IMAGE'))
99 # Unwrap Constraint
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
104 # Texture Projection
105 layout.menu(MUV_MT_TextureProjection.bl_idname, text="Texture Projection")
106 # UVW
107 layout.menu(MUV_MT_UVW.bl_idname, text="UVW")
110 def view3d_object_menu_fn(self, _):
111 layout = self.layout
113 layout.separator()
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):
120 layout = self.layout
121 sc = context.scene
123 layout.separator()
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")
128 layout.separator()
129 layout.label(text="UV Manipulation", icon=compat.icon('IMAGE'))
130 # Clip UV
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
134 # Pack UV
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
138 # Select UV
139 layout.menu(MUV_MT_SelectUV.bl_idname, text="Select UV")
140 # Smooth 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
145 # Align UV
146 layout.menu(MUV_MT_AlignUV.bl_idname, text="Align UV")
148 layout.separator()
149 layout.label(text="Editor Enhancement", icon=compat.icon('IMAGE'))
150 # Align UV Cursor
151 layout.menu(MUV_MT_AlignUVCursor.bl_idname, text="Align UV Cursor")
152 # UV Bounding Box
153 layout.prop(sc, "muv_uv_bounding_box_show", text="UV Bounding Box")
154 # UV Inspection
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)
176 if enabled:
177 common.enable_debugg_mode()
178 else:
179 common.disable_debug_mode()
180 return enabled
183 @BlClassRegistry()
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']:
192 add_builtin_menu()
193 else:
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",
200 default=True,
201 update=update_enable_builtin_menu,
204 # enable debug mode
205 enable_debug_mode = BoolProperty(
206 name="Debug Mode",
207 description="Enable debugging mode",
208 default=False,
209 set=set_debug_mode,
210 get=get_debug_mode,
213 # for UV Sculpt
214 uv_sculpt_brush_color = FloatVectorProperty(
215 name="Color",
216 description="Color",
217 default=(1.0, 0.4, 0.4, 1.0),
218 min=0.0,
219 max=1.0,
220 size=4,
221 subtype='COLOR'
224 # for Overlapped UV
225 uv_inspection_overlapped_color = FloatVectorProperty(
226 name="Color",
227 description="Color",
228 default=(0.0, 0.0, 1.0, 0.3),
229 min=0.0,
230 max=1.0,
231 size=4,
232 subtype='COLOR'
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),
238 min=0.0,
239 max=1.0,
240 size=4,
241 subtype='COLOR'
244 # for Flipped UV
245 uv_inspection_flipped_color = FloatVectorProperty(
246 name="Color",
247 description="Color",
248 default=(1.0, 0.0, 0.0, 0.3),
249 min=0.0,
250 max=1.0,
251 size=4,
252 subtype='COLOR'
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),
258 min=0.0,
259 max=1.0,
260 size=4,
261 subtype='COLOR'
264 # for Texture Projection
265 texture_projection_canvas_padding = FloatVectorProperty(
266 name="Canvas Padding",
267 description="Canvas Padding",
268 size=2,
269 max=50.0,
270 min=0.0,
271 default=(20.0, 20.0))
273 # for UV Bounding Box
274 uv_bounding_box_cp_size = FloatProperty(
275 name="Size",
276 description="Control Point Size",
277 default=6.0,
278 min=3.0,
279 max=100.0)
280 uv_bounding_box_cp_react_size = FloatProperty(
281 name="React Size",
282 description="Size event fired",
283 default=10.0,
284 min=3.0,
285 max=100.0)
287 # for UI
288 category = EnumProperty(
289 name="Category",
290 description="Preferences Category",
291 items=[
292 ('INFO', "Information", "Information about this add-on"),
293 ('CONFIG', "Configuration", "Configuration about this add-on"),
295 default='INFO'
297 info_desc_expanded = BoolProperty(
298 name="Description",
299 description="Description",
300 default=False
302 info_loc_expanded = BoolProperty(
303 name="Location",
304 description="Location",
305 default=False
307 conf_uv_sculpt_expanded = BoolProperty(
308 name="UV Sculpt",
309 description="UV Sculpt",
310 default=False
312 conf_uv_inspection_expanded = BoolProperty(
313 name="UV Inspection",
314 description="UV Inspection",
315 default=False
317 conf_texture_projection_expanded = BoolProperty(
318 name="Texture Projection",
319 description="Texture Projection",
320 default=False
322 conf_uv_bounding_box_expanded = BoolProperty(
323 name="UV Bounding Box",
324 description="UV Bounding Box",
325 default=False
328 def draw(self, _):
329 layout = self.layout
331 layout.row().prop(self, "category", expand=True)
333 if self.category == 'INFO':
334 layout.separator()
336 layout.prop(
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" +
343 " features.")
344 col.label(text="See tutorial page if you are new to this" +
345 " add-on.")
346 col.label(text="https://github.com/nutti/Magic-UV" +
347 "/wiki/Tutorial")
349 layout.prop(
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':
426 layout.separator()
428 layout.prop(self, "enable_builtin_menu", text="Built-in Menu")
429 layout.prop(self, "enable_debug_mode", text="Debug Mode")
431 layout.separator()
433 layout.prop(
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)
441 col = sp.column()
442 col.label(text="Brush Color:")
443 col.prop(self, "uv_sculpt_brush_color", text="")
444 layout.separator()
446 layout.prop(
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)
454 col = sp.column()
455 col.label(text="Overlapped UV Color:")
456 col.prop(self, "uv_inspection_overlapped_color", text="")
457 sp = compat.layout_split(sp, 0.45)
458 col = sp.column()
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)
465 col = sp.column()
466 col.label(text="Overlapped UV Color (View3D):")
467 col.prop(self, "uv_inspection_overlapped_color_for_v3d",
468 text="")
469 sp = compat.layout_split(sp, 0.45)
470 col = sp.column()
471 col.label(text="Flipped UV Color (View3D):")
472 col.prop(self, "uv_inspection_flipped_color_for_v3d",
473 text="")
475 layout.separator()
477 layout.prop(
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)
487 col = sp.column()
488 col.prop(self, "texture_projection_canvas_padding")
489 layout.separator()
491 layout.prop(
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)
500 col = sp.column()
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")
504 layout.separator()