Fix: Node Wrangler: new reroutes offset when output hidden
[blender-addons.git] / magic_uv / preferences.py
blob37723d597ecd804b98c0a2bd6932dedf6ee5f82f
1 # SPDX-License-Identifier: GPL-2.0-or-later
3 __author__ = "Nutti <nutti.metro@gmail.com>"
4 __status__ = "production"
5 __version__ = "6.6"
6 __date__ = "22 Apr 2022"
8 import bpy
9 from bpy.props import (
10 FloatProperty,
11 FloatVectorProperty,
12 BoolProperty,
13 EnumProperty,
15 from bpy.types import AddonPreferences
17 from . import common
18 from .op.clip_uv import MUV_OT_ClipUV
19 from .op.flip_rotate_uv import MUV_OT_FlipRotateUV
20 from .op.mirror_uv import MUV_OT_MirrorUV
21 from .op.move_uv import MUV_OT_MoveUV
22 from .op.unwrap_constraint import MUV_OT_UnwrapConstraint
23 from .op.pack_uv import MUV_OT_PackUV
24 from .op.smooth_uv import MUV_OT_SmoothUV
25 from .ui.VIEW3D_MT_uv_map import (
26 MUV_MT_CopyPasteUV,
27 MUV_MT_TransferUV,
28 MUV_MT_WorldScaleUV,
29 MUV_MT_PreserveUVAspect,
30 MUV_MT_TextureLock,
31 MUV_MT_TextureWrap,
32 MUV_MT_TextureProjection,
33 MUV_MT_UVW,
35 from .ui.VIEW3D_MT_object import MUV_MT_CopyPasteUV_Object
36 from .ui.IMAGE_MT_uvs import (
37 MUV_MT_CopyPasteUV_UVEdit,
38 MUV_MT_SelectUV,
39 MUV_MT_AlignUV,
40 MUV_MT_AlignUVCursor,
41 MUV_MT_UVInspection,
43 from .utils.bl_class_registry import BlClassRegistry
44 from .utils import compatibility as compat
47 def view3d_uvmap_menu_fn(self, context):
48 layout = self.layout
49 sc = context.scene
51 layout.separator()
52 layout.label(text="Copy/Paste UV", icon=compat.icon('IMAGE'))
53 # Copy/Paste UV
54 layout.menu(MUV_MT_CopyPasteUV.bl_idname, text="Copy/Paste UV")
55 # Transfer UV
56 layout.menu(MUV_MT_TransferUV.bl_idname, text="Transfer UV")
58 layout.separator()
59 layout.label(text="UV Manipulation", icon=compat.icon('IMAGE'))
60 # Flip/Rotate UV
61 ops = layout.operator(MUV_OT_FlipRotateUV.bl_idname, text="Flip/Rotate UV")
62 ops.seams = sc.muv_flip_rotate_uv_seams
63 # Mirror UV
64 ops = layout.operator(MUV_OT_MirrorUV.bl_idname, text="Mirror UV")
65 ops.axis = sc.muv_mirror_uv_axis
66 # Move UV
67 layout.operator(MUV_OT_MoveUV.bl_idname, text="Move UV")
68 # World Scale UV
69 layout.menu(MUV_MT_WorldScaleUV.bl_idname, text="World Scale UV")
70 # Preserve UV
71 layout.menu(MUV_MT_PreserveUVAspect.bl_idname, text="Preserve UV")
72 # Texture Lock
73 layout.menu(MUV_MT_TextureLock.bl_idname, text="Texture Lock")
74 # Texture Wrap
75 layout.menu(MUV_MT_TextureWrap.bl_idname, text="Texture Wrap")
76 # UV Sculpt
77 layout.prop(sc, "muv_uv_sculpt_enable", text="UV Sculpt")
79 layout.separator()
80 layout.label(text="UV Mapping", icon=compat.icon('IMAGE'))
81 # Unwrap Constraint
82 ops = layout.operator(MUV_OT_UnwrapConstraint.bl_idname,
83 text="Unwrap Constraint")
84 ops.u_const = sc.muv_unwrap_constraint_u_const
85 ops.v_const = sc.muv_unwrap_constraint_v_const
86 # Texture Projection
87 layout.menu(MUV_MT_TextureProjection.bl_idname, text="Texture Projection")
88 # UVW
89 layout.menu(MUV_MT_UVW.bl_idname, text="UVW")
92 def view3d_object_menu_fn(self, _):
93 layout = self.layout
95 layout.separator()
96 layout.label(text="Copy/Paste UV", icon=compat.icon('IMAGE'))
97 # Copy/Paste UV (Among Object)
98 layout.menu(MUV_MT_CopyPasteUV_Object.bl_idname, text="Copy/Paste UV")
101 def image_uvs_menu_fn(self, context):
102 layout = self.layout
103 sc = context.scene
105 layout.separator()
106 layout.label(text="Copy/Paste UV", icon=compat.icon('IMAGE'))
107 # Copy/Paste UV (on UV/Image Editor)
108 layout.menu(MUV_MT_CopyPasteUV_UVEdit.bl_idname, text="Copy/Paste UV")
110 layout.separator()
111 layout.label(text="UV Manipulation", icon=compat.icon('IMAGE'))
112 # Clip UV
113 ops = layout.operator(MUV_OT_ClipUV.bl_idname, text="Clip UV")
114 ops.clip_uv_range_max = sc.muv_clip_uv_range_max
115 ops.clip_uv_range_min = sc.muv_clip_uv_range_min
116 # Pack UV
117 ops = layout.operator(MUV_OT_PackUV.bl_idname, text="Pack UV")
118 ops.allowable_center_deviation = sc.muv_pack_uv_allowable_center_deviation
119 ops.allowable_size_deviation = sc.muv_pack_uv_allowable_size_deviation
120 ops.accurate_island_copy = sc.muv_pack_uv_accurate_island_copy
121 ops.stride = sc.muv_pack_uv_stride
122 ops.apply_pack_uv = sc.muv_pack_uv_apply_pack_uv
123 # Select UV
124 layout.menu(MUV_MT_SelectUV.bl_idname, text="Select UV")
125 # Smooth UV
126 ops = layout.operator(MUV_OT_SmoothUV.bl_idname, text="Smooth")
127 ops.transmission = sc.muv_smooth_uv_transmission
128 ops.select = sc.muv_smooth_uv_select
129 ops.mesh_infl = sc.muv_smooth_uv_mesh_infl
130 # Align UV
131 layout.menu(MUV_MT_AlignUV.bl_idname, text="Align UV")
133 layout.separator()
134 layout.label(text="Editor Enhancement", icon=compat.icon('IMAGE'))
135 # Align UV Cursor
136 layout.menu(MUV_MT_AlignUVCursor.bl_idname, text="Align UV Cursor")
137 # UV Bounding Box
138 layout.prop(sc, "muv_uv_bounding_box_show", text="UV Bounding Box")
139 # UV Inspection
140 layout.menu(MUV_MT_UVInspection.bl_idname, text="UV Inspection")
143 def add_builtin_menu():
144 bpy.types.VIEW3D_MT_uv_map.append(view3d_uvmap_menu_fn)
145 bpy.types.VIEW3D_MT_object.append(view3d_object_menu_fn)
146 bpy.types.IMAGE_MT_uvs.append(image_uvs_menu_fn)
149 def remove_builtin_menu():
150 bpy.types.IMAGE_MT_uvs.remove(image_uvs_menu_fn)
151 bpy.types.VIEW3D_MT_object.remove(view3d_object_menu_fn)
152 bpy.types.VIEW3D_MT_uv_map.remove(view3d_uvmap_menu_fn)
155 def set_debug_mode(self, value):
156 self['enable_debug_mode'] = value
159 def get_debug_mode(self):
160 enabled = self.get('enable_debug_mode', False)
161 if enabled:
162 common.enable_debugg_mode()
163 else:
164 common.disable_debug_mode()
165 return enabled
168 @BlClassRegistry()
169 @compat.make_annotations
170 class MUV_Preferences(AddonPreferences):
171 """Preferences class: Preferences for this add-on"""
173 bl_idname = "magic_uv"
175 def update_enable_builtin_menu(self, _):
176 if self['enable_builtin_menu']:
177 add_builtin_menu()
178 else:
179 remove_builtin_menu()
181 # enable to add features to built-in menu
182 enable_builtin_menu = BoolProperty(
183 name="Built-in Menu",
184 description="Enable built-in menu",
185 default=True,
186 update=update_enable_builtin_menu,
189 # enable debug mode
190 enable_debug_mode = BoolProperty(
191 name="Debug Mode",
192 description="Enable debugging mode",
193 default=False,
194 set=set_debug_mode,
195 get=get_debug_mode,
198 # for UV Sculpt
199 uv_sculpt_brush_color = FloatVectorProperty(
200 name="Color",
201 description="Color",
202 default=(1.0, 0.4, 0.4, 1.0),
203 min=0.0,
204 max=1.0,
205 size=4,
206 subtype='COLOR'
209 # for Overlapped UV
210 uv_inspection_overlapped_color = FloatVectorProperty(
211 name="Color",
212 description="Color",
213 default=(0.0, 0.0, 1.0, 0.3),
214 min=0.0,
215 max=1.0,
216 size=4,
217 subtype='COLOR'
219 uv_inspection_overlapped_color_for_v3d = FloatVectorProperty(
220 name="Color (View3D)",
221 description="Color in View3D",
222 default=(0.0, 0.0, 1.0, 0.5),
223 min=0.0,
224 max=1.0,
225 size=4,
226 subtype='COLOR'
229 # for Flipped UV
230 uv_inspection_flipped_color = FloatVectorProperty(
231 name="Color",
232 description="Color",
233 default=(1.0, 0.0, 0.0, 0.3),
234 min=0.0,
235 max=1.0,
236 size=4,
237 subtype='COLOR'
239 uv_inspection_flipped_color_for_v3d = FloatVectorProperty(
240 name="Color (View3D)",
241 description="Color in View3D",
242 default=(1.0, 0.0, 0.0, 0.5),
243 min=0.0,
244 max=1.0,
245 size=4,
246 subtype='COLOR'
249 # for Texture Projection
250 texture_projection_canvas_padding = FloatVectorProperty(
251 name="Canvas Padding",
252 description="Canvas Padding",
253 size=2,
254 max=50.0,
255 min=0.0,
256 default=(20.0, 20.0))
258 # for UV Bounding Box
259 uv_bounding_box_cp_size = FloatProperty(
260 name="Size",
261 description="Control Point Size",
262 default=6.0,
263 min=3.0,
264 max=100.0)
265 uv_bounding_box_cp_react_size = FloatProperty(
266 name="React Size",
267 description="Size event fired",
268 default=10.0,
269 min=3.0,
270 max=100.0)
272 # for UI
273 category = EnumProperty(
274 name="Category",
275 description="Preferences Category",
276 items=[
277 ('INFO', "Information", "Information about this add-on"),
278 ('CONFIG', "Configuration", "Configuration about this add-on"),
280 default='INFO'
282 info_desc_expanded = BoolProperty(
283 name="Description",
284 description="Description",
285 default=False
287 info_loc_expanded = BoolProperty(
288 name="Location",
289 description="Location",
290 default=False
292 conf_uv_sculpt_expanded = BoolProperty(
293 name="UV Sculpt",
294 description="UV Sculpt",
295 default=False
297 conf_uv_inspection_expanded = BoolProperty(
298 name="UV Inspection",
299 description="UV Inspection",
300 default=False
302 conf_texture_projection_expanded = BoolProperty(
303 name="Texture Projection",
304 description="Texture Projection",
305 default=False
307 conf_uv_bounding_box_expanded = BoolProperty(
308 name="UV Bounding Box",
309 description="UV Bounding Box",
310 default=False
313 def draw(self, _):
314 layout = self.layout
316 layout.row().prop(self, "category", expand=True)
318 if self.category == 'INFO':
319 layout.separator()
321 layout.prop(
322 self, "info_desc_expanded", text="Description",
323 icon='DISCLOSURE_TRI_DOWN' if self.info_desc_expanded
324 else 'DISCLOSURE_TRI_RIGHT')
325 if self.info_desc_expanded:
326 col = layout.column(align=True)
327 col.label(text="Magic UV is composed of many UV editing" +
328 " features.")
329 col.label(text="See tutorial page if you are new to this" +
330 " add-on.")
331 col.label(text="https://github.com/nutti/Magic-UV" +
332 "/wiki/Tutorial")
334 layout.prop(
335 self, "info_loc_expanded", text="Location",
336 icon='DISCLOSURE_TRI_DOWN' if self.info_loc_expanded
337 else 'DISCLOSURE_TRI_RIGHT')
338 if self.info_loc_expanded:
339 row = layout.row(align=True)
340 sp = compat.layout_split(row, 0.5)
341 sp.label(text="3D View > Sidebar > " +
342 "Copy/Paste UV (Object mode)")
343 sp = compat.layout_split(sp, 1.0)
344 col = sp.column(align=True)
345 col.label(text="Copy/Paste UV (Among objects)")
347 row = layout.row(align=True)
348 sp = compat.layout_split(row, 0.5)
349 sp.label(text="3D View > Sidebar > " +
350 "Copy/Paste UV (Edit mode)")
351 sp = compat.layout_split(sp, 1.0)
352 col = sp.column(align=True)
353 col.label(text="Copy/Paste UV (Among faces in 3D View)")
354 col.label(text="Transfer UV")
356 row = layout.row(align=True)
357 sp = compat.layout_split(row, 0.5)
358 sp.label(text="3D View > Sidebar > " +
359 "UV Manipulation (Edit mode)")
360 sp = compat.layout_split(sp, 1.0)
361 col = sp.column(align=True)
362 col.label(text="Flip/Rotate UV")
363 col.label(text="Mirror UV")
364 col.label(text="Move UV")
365 col.label(text="World Scale UV")
366 col.label(text="Preserve UV Aspect")
367 col.label(text="Texture Lock")
368 col.label(text="Texture Wrap")
369 col.label(text="UV Sculpt")
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="Unwrap Constraint")
378 col.label(text="Texture Projection")
379 col.label(text="UVW")
381 row = layout.row(align=True)
382 sp = compat.layout_split(row, 0.5)
383 sp.label(text="UV/Image Editor > Sidebar > Copy/Paste UV")
384 sp = compat.layout_split(sp, 1.0)
385 col = sp.column(align=True)
386 col.label(text="Copy/Paste UV " +
387 "(Among faces in UV/Image Editor)")
389 row = layout.row(align=True)
390 sp = compat.layout_split(row, 0.5)
391 sp.label(text="UV/Image Editor > Sidebar > UV Manipulation")
392 sp = compat.layout_split(sp, 1.0)
393 col = sp.column(align=True)
394 col.label(text="Align UV")
395 col.label(text="Smooth UV")
396 col.label(text="Select UV")
397 col.label(text="Pack UV (Extension)")
399 row = layout.row(align=True)
400 sp = compat.layout_split(row, 0.5)
401 sp.label(text="UV/Image Editor > Sidebar > " +
402 "Editor Enhancement")
403 sp = compat.layout_split(sp, 1.0)
404 col = sp.column(align=True)
405 col.label(text="Align UV Cursor")
406 col.label(text="UV Cursor Location")
407 col.label(text="UV Bounding Box")
408 col.label(text="UV Inspection")
410 elif self.category == 'CONFIG':
411 layout.separator()
413 layout.prop(self, "enable_builtin_menu", text="Built-in Menu")
414 layout.prop(self, "enable_debug_mode", text="Debug Mode")
416 layout.separator()
418 layout.prop(
419 self, "conf_uv_sculpt_expanded", text="UV Sculpt",
420 icon='DISCLOSURE_TRI_DOWN' if self.conf_uv_sculpt_expanded
421 else 'DISCLOSURE_TRI_RIGHT')
422 if self.conf_uv_sculpt_expanded:
423 sp = compat.layout_split(layout, 0.05)
424 col = sp.column() # spacer
425 sp = compat.layout_split(sp, 0.3)
426 col = sp.column()
427 col.label(text="Brush Color:")
428 col.prop(self, "uv_sculpt_brush_color", text="")
429 layout.separator()
431 layout.prop(
432 self, "conf_uv_inspection_expanded", text="UV Inspection",
433 icon='DISCLOSURE_TRI_DOWN' if self.conf_uv_inspection_expanded
434 else 'DISCLOSURE_TRI_RIGHT')
435 if self.conf_uv_inspection_expanded:
436 sp = compat.layout_split(layout, 0.05)
437 col = sp.column() # spacer
438 sp = compat.layout_split(sp, 0.3)
439 col = sp.column()
440 col.label(text="Overlapped UV Color:")
441 col.prop(self, "uv_inspection_overlapped_color", text="")
442 sp = compat.layout_split(sp, 0.45)
443 col = sp.column()
444 col.label(text="Flipped UV Color:")
445 col.prop(self, "uv_inspection_flipped_color", text="")
447 sp = compat.layout_split(layout, 0.05)
448 col = sp.column() # spacer
449 sp = compat.layout_split(sp, 0.3)
450 col = sp.column()
451 col.label(text="Overlapped UV Color (View3D):")
452 col.prop(self, "uv_inspection_overlapped_color_for_v3d",
453 text="")
454 sp = compat.layout_split(sp, 0.45)
455 col = sp.column()
456 col.label(text="Flipped UV Color (View3D):")
457 col.prop(self, "uv_inspection_flipped_color_for_v3d",
458 text="")
460 layout.separator()
462 layout.prop(
463 self, "conf_texture_projection_expanded",
464 text="Texture Projection",
465 icon='DISCLOSURE_TRI_DOWN'
466 if self.conf_texture_projection_expanded
467 else 'DISCLOSURE_TRI_RIGHT')
468 if self.conf_texture_projection_expanded:
469 sp = compat.layout_split(layout, 0.05)
470 col = sp.column() # spacer
471 sp = compat.layout_split(sp, 0.3)
472 col = sp.column()
473 col.prop(self, "texture_projection_canvas_padding")
474 layout.separator()
476 layout.prop(
477 self, "conf_uv_bounding_box_expanded", text="UV Bounding Box",
478 icon='DISCLOSURE_TRI_DOWN'
479 if self.conf_uv_bounding_box_expanded
480 else 'DISCLOSURE_TRI_RIGHT')
481 if self.conf_uv_bounding_box_expanded:
482 sp = compat.layout_split(layout, 0.05)
483 col = sp.column() # spacer
484 sp = compat.layout_split(sp, 0.3)
485 col = sp.column()
486 col.label(text="Control Point:")
487 col.prop(self, "uv_bounding_box_cp_size")
488 col.prop(self, "uv_bounding_box_cp_react_size")
489 layout.separator()