Node Wrangler: do not add reroutes to unavailable outputs
[blender-addons.git] / magic_uv / preferences.py
blobd0c50ab9ca4030c082a124aa7264747a1feea80f
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"
7 __version__ = "6.6"
8 __date__ = "22 Apr 2022"
10 import bpy
11 from bpy.props import (
12 FloatProperty,
13 FloatVectorProperty,
14 BoolProperty,
15 EnumProperty,
17 from bpy.types import AddonPreferences
19 from . import common
20 from .op.clip_uv import MUV_OT_ClipUV
21 from .op.flip_rotate_uv import MUV_OT_FlipRotateUV
22 from .op.mirror_uv import MUV_OT_MirrorUV
23 from .op.move_uv import MUV_OT_MoveUV
24 from .op.unwrap_constraint import MUV_OT_UnwrapConstraint
25 from .op.pack_uv import MUV_OT_PackUV
26 from .op.smooth_uv import MUV_OT_SmoothUV
27 from .ui.VIEW3D_MT_uv_map import (
28 MUV_MT_CopyPasteUV,
29 MUV_MT_TransferUV,
30 MUV_MT_WorldScaleUV,
31 MUV_MT_PreserveUVAspect,
32 MUV_MT_TextureLock,
33 MUV_MT_TextureWrap,
34 MUV_MT_TextureProjection,
35 MUV_MT_UVW,
37 from .ui.VIEW3D_MT_object import MUV_MT_CopyPasteUV_Object
38 from .ui.IMAGE_MT_uvs import (
39 MUV_MT_CopyPasteUV_UVEdit,
40 MUV_MT_SelectUV,
41 MUV_MT_AlignUV,
42 MUV_MT_AlignUVCursor,
43 MUV_MT_UVInspection,
45 from .utils.bl_class_registry import BlClassRegistry
46 from .utils import compatibility as compat
49 def view3d_uvmap_menu_fn(self, context):
50 layout = self.layout
51 sc = context.scene
53 layout.separator()
54 layout.label(text="Copy/Paste UV", icon=compat.icon('IMAGE'))
55 # Copy/Paste UV
56 layout.menu(MUV_MT_CopyPasteUV.bl_idname, text="Copy/Paste UV")
57 # Transfer UV
58 layout.menu(MUV_MT_TransferUV.bl_idname, text="Transfer UV")
60 layout.separator()
61 layout.label(text="UV Manipulation", icon=compat.icon('IMAGE'))
62 # Flip/Rotate UV
63 ops = layout.operator(MUV_OT_FlipRotateUV.bl_idname, text="Flip/Rotate UV")
64 ops.seams = sc.muv_flip_rotate_uv_seams
65 # Mirror UV
66 ops = layout.operator(MUV_OT_MirrorUV.bl_idname, text="Mirror UV")
67 ops.axis = sc.muv_mirror_uv_axis
68 # Move UV
69 layout.operator(MUV_OT_MoveUV.bl_idname, text="Move UV")
70 # World Scale UV
71 layout.menu(MUV_MT_WorldScaleUV.bl_idname, text="World Scale UV")
72 # Preserve UV
73 layout.menu(MUV_MT_PreserveUVAspect.bl_idname, text="Preserve UV")
74 # Texture Lock
75 layout.menu(MUV_MT_TextureLock.bl_idname, text="Texture Lock")
76 # Texture Wrap
77 layout.menu(MUV_MT_TextureWrap.bl_idname, text="Texture Wrap")
78 # UV Sculpt
79 layout.prop(sc, "muv_uv_sculpt_enable", text="UV Sculpt")
81 layout.separator()
82 layout.label(text="UV Mapping", icon=compat.icon('IMAGE'))
83 # Unwrap Constraint
84 ops = layout.operator(MUV_OT_UnwrapConstraint.bl_idname,
85 text="Unwrap Constraint")
86 ops.u_const = sc.muv_unwrap_constraint_u_const
87 ops.v_const = sc.muv_unwrap_constraint_v_const
88 # Texture Projection
89 layout.menu(MUV_MT_TextureProjection.bl_idname, text="Texture Projection")
90 # UVW
91 layout.menu(MUV_MT_UVW.bl_idname, text="UVW")
94 def view3d_object_menu_fn(self, _):
95 layout = self.layout
97 layout.separator()
98 layout.label(text="Copy/Paste UV", icon=compat.icon('IMAGE'))
99 # Copy/Paste UV (Among Object)
100 layout.menu(MUV_MT_CopyPasteUV_Object.bl_idname, text="Copy/Paste UV")
103 def image_uvs_menu_fn(self, context):
104 layout = self.layout
105 sc = context.scene
107 layout.separator()
108 layout.label(text="Copy/Paste UV", icon=compat.icon('IMAGE'))
109 # Copy/Paste UV (on UV/Image Editor)
110 layout.menu(MUV_MT_CopyPasteUV_UVEdit.bl_idname, text="Copy/Paste UV")
112 layout.separator()
113 layout.label(text="UV Manipulation", icon=compat.icon('IMAGE'))
114 # Clip UV
115 ops = layout.operator(MUV_OT_ClipUV.bl_idname, text="Clip UV")
116 ops.clip_uv_range_max = sc.muv_clip_uv_range_max
117 ops.clip_uv_range_min = sc.muv_clip_uv_range_min
118 # Pack UV
119 ops = layout.operator(MUV_OT_PackUV.bl_idname, text="Pack UV")
120 ops.allowable_center_deviation = sc.muv_pack_uv_allowable_center_deviation
121 ops.allowable_size_deviation = sc.muv_pack_uv_allowable_size_deviation
122 ops.accurate_island_copy = sc.muv_pack_uv_accurate_island_copy
123 ops.stride = sc.muv_pack_uv_stride
124 ops.apply_pack_uv = sc.muv_pack_uv_apply_pack_uv
125 # Select UV
126 layout.menu(MUV_MT_SelectUV.bl_idname, text="Select UV")
127 # Smooth UV
128 ops = layout.operator(MUV_OT_SmoothUV.bl_idname, text="Smooth")
129 ops.transmission = sc.muv_smooth_uv_transmission
130 ops.select = sc.muv_smooth_uv_select
131 ops.mesh_infl = sc.muv_smooth_uv_mesh_infl
132 # Align UV
133 layout.menu(MUV_MT_AlignUV.bl_idname, text="Align UV")
135 layout.separator()
136 layout.label(text="Editor Enhancement", icon=compat.icon('IMAGE'))
137 # Align UV Cursor
138 layout.menu(MUV_MT_AlignUVCursor.bl_idname, text="Align UV Cursor")
139 # UV Bounding Box
140 layout.prop(sc, "muv_uv_bounding_box_show", text="UV Bounding Box")
141 # UV Inspection
142 layout.menu(MUV_MT_UVInspection.bl_idname, text="UV Inspection")
145 def add_builtin_menu():
146 bpy.types.VIEW3D_MT_uv_map.append(view3d_uvmap_menu_fn)
147 bpy.types.VIEW3D_MT_object.append(view3d_object_menu_fn)
148 bpy.types.IMAGE_MT_uvs.append(image_uvs_menu_fn)
151 def remove_builtin_menu():
152 bpy.types.IMAGE_MT_uvs.remove(image_uvs_menu_fn)
153 bpy.types.VIEW3D_MT_object.remove(view3d_object_menu_fn)
154 bpy.types.VIEW3D_MT_uv_map.remove(view3d_uvmap_menu_fn)
157 def set_debug_mode(self, value):
158 self['enable_debug_mode'] = value
161 def get_debug_mode(self):
162 enabled = self.get('enable_debug_mode', False)
163 if enabled:
164 common.enable_debugg_mode()
165 else:
166 common.disable_debug_mode()
167 return enabled
170 @BlClassRegistry()
171 @compat.make_annotations
172 class MUV_Preferences(AddonPreferences):
173 """Preferences class: Preferences for this add-on"""
175 bl_idname = "magic_uv"
177 def update_enable_builtin_menu(self, _):
178 if self['enable_builtin_menu']:
179 add_builtin_menu()
180 else:
181 remove_builtin_menu()
183 # enable to add features to built-in menu
184 enable_builtin_menu = BoolProperty(
185 name="Built-in Menu",
186 description="Enable built-in menu",
187 default=True,
188 update=update_enable_builtin_menu,
191 # enable debug mode
192 enable_debug_mode = BoolProperty(
193 name="Debug Mode",
194 description="Enable debugging mode",
195 default=False,
196 set=set_debug_mode,
197 get=get_debug_mode,
200 # for UV Sculpt
201 uv_sculpt_brush_color = FloatVectorProperty(
202 name="Color",
203 description="Color",
204 default=(1.0, 0.4, 0.4, 1.0),
205 min=0.0,
206 max=1.0,
207 size=4,
208 subtype='COLOR'
211 # for Overlapped UV
212 uv_inspection_overlapped_color = FloatVectorProperty(
213 name="Color",
214 description="Color",
215 default=(0.0, 0.0, 1.0, 0.3),
216 min=0.0,
217 max=1.0,
218 size=4,
219 subtype='COLOR'
221 uv_inspection_overlapped_color_for_v3d = FloatVectorProperty(
222 name="Color (View3D)",
223 description="Color in View3D",
224 default=(0.0, 0.0, 1.0, 0.5),
225 min=0.0,
226 max=1.0,
227 size=4,
228 subtype='COLOR'
231 # for Flipped UV
232 uv_inspection_flipped_color = FloatVectorProperty(
233 name="Color",
234 description="Color",
235 default=(1.0, 0.0, 0.0, 0.3),
236 min=0.0,
237 max=1.0,
238 size=4,
239 subtype='COLOR'
241 uv_inspection_flipped_color_for_v3d = FloatVectorProperty(
242 name="Color (View3D)",
243 description="Color in View3D",
244 default=(1.0, 0.0, 0.0, 0.5),
245 min=0.0,
246 max=1.0,
247 size=4,
248 subtype='COLOR'
251 # for Texture Projection
252 texture_projection_canvas_padding = FloatVectorProperty(
253 name="Canvas Padding",
254 description="Canvas Padding",
255 size=2,
256 max=50.0,
257 min=0.0,
258 default=(20.0, 20.0))
260 # for UV Bounding Box
261 uv_bounding_box_cp_size = FloatProperty(
262 name="Size",
263 description="Control Point Size",
264 default=6.0,
265 min=3.0,
266 max=100.0)
267 uv_bounding_box_cp_react_size = FloatProperty(
268 name="React Size",
269 description="Size event fired",
270 default=10.0,
271 min=3.0,
272 max=100.0)
274 # for UI
275 category = EnumProperty(
276 name="Category",
277 description="Preferences Category",
278 items=[
279 ('INFO', "Information", "Information about this add-on"),
280 ('CONFIG', "Configuration", "Configuration about this add-on"),
282 default='INFO'
284 info_desc_expanded = BoolProperty(
285 name="Description",
286 description="Description",
287 default=False
289 info_loc_expanded = BoolProperty(
290 name="Location",
291 description="Location",
292 default=False
294 conf_uv_sculpt_expanded = BoolProperty(
295 name="UV Sculpt",
296 description="UV Sculpt",
297 default=False
299 conf_uv_inspection_expanded = BoolProperty(
300 name="UV Inspection",
301 description="UV Inspection",
302 default=False
304 conf_texture_projection_expanded = BoolProperty(
305 name="Texture Projection",
306 description="Texture Projection",
307 default=False
309 conf_uv_bounding_box_expanded = BoolProperty(
310 name="UV Bounding Box",
311 description="UV Bounding Box",
312 default=False
315 def draw(self, _):
316 layout = self.layout
318 layout.row().prop(self, "category", expand=True)
320 if self.category == 'INFO':
321 layout.separator()
323 layout.prop(
324 self, "info_desc_expanded", text="Description",
325 icon='DISCLOSURE_TRI_DOWN' if self.info_desc_expanded
326 else 'DISCLOSURE_TRI_RIGHT')
327 if self.info_desc_expanded:
328 col = layout.column(align=True)
329 col.label(text="Magic UV is composed of many UV editing" +
330 " features.")
331 col.label(text="See tutorial page if you are new to this" +
332 " add-on.")
333 col.label(text="https://github.com/nutti/Magic-UV" +
334 "/wiki/Tutorial")
336 layout.prop(
337 self, "info_loc_expanded", text="Location",
338 icon='DISCLOSURE_TRI_DOWN' if self.info_loc_expanded
339 else 'DISCLOSURE_TRI_RIGHT')
340 if self.info_loc_expanded:
341 row = layout.row(align=True)
342 sp = compat.layout_split(row, 0.5)
343 sp.label(text="3D View > Sidebar > " +
344 "Copy/Paste UV (Object mode)")
345 sp = compat.layout_split(sp, 1.0)
346 col = sp.column(align=True)
347 col.label(text="Copy/Paste UV (Among objects)")
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 (Edit mode)")
353 sp = compat.layout_split(sp, 1.0)
354 col = sp.column(align=True)
355 col.label(text="Copy/Paste UV (Among faces in 3D View)")
356 col.label(text="Transfer UV")
358 row = layout.row(align=True)
359 sp = compat.layout_split(row, 0.5)
360 sp.label(text="3D View > Sidebar > " +
361 "UV Manipulation (Edit mode)")
362 sp = compat.layout_split(sp, 1.0)
363 col = sp.column(align=True)
364 col.label(text="Flip/Rotate UV")
365 col.label(text="Mirror UV")
366 col.label(text="Move UV")
367 col.label(text="World Scale UV")
368 col.label(text="Preserve UV Aspect")
369 col.label(text="Texture Lock")
370 col.label(text="Texture Wrap")
371 col.label(text="UV Sculpt")
373 row = layout.row(align=True)
374 sp = compat.layout_split(row, 0.5)
375 sp.label(text="3D View > Sidebar > " +
376 "UV Manipulation (Edit mode)")
377 sp = compat.layout_split(sp, 1.0)
378 col = sp.column(align=True)
379 col.label(text="Unwrap Constraint")
380 col.label(text="Texture Projection")
381 col.label(text="UVW")
383 row = layout.row(align=True)
384 sp = compat.layout_split(row, 0.5)
385 sp.label(text="UV/Image Editor > Sidebar > Copy/Paste UV")
386 sp = compat.layout_split(sp, 1.0)
387 col = sp.column(align=True)
388 col.label(text="Copy/Paste UV " +
389 "(Among faces in UV/Image Editor)")
391 row = layout.row(align=True)
392 sp = compat.layout_split(row, 0.5)
393 sp.label(text="UV/Image Editor > Sidebar > UV Manipulation")
394 sp = compat.layout_split(sp, 1.0)
395 col = sp.column(align=True)
396 col.label(text="Align UV")
397 col.label(text="Smooth UV")
398 col.label(text="Select UV")
399 col.label(text="Pack UV (Extension)")
401 row = layout.row(align=True)
402 sp = compat.layout_split(row, 0.5)
403 sp.label(text="UV/Image Editor > Sidebar > " +
404 "Editor Enhancement")
405 sp = compat.layout_split(sp, 1.0)
406 col = sp.column(align=True)
407 col.label(text="Align UV Cursor")
408 col.label(text="UV Cursor Location")
409 col.label(text="UV Bounding Box")
410 col.label(text="UV Inspection")
412 elif self.category == 'CONFIG':
413 layout.separator()
415 layout.prop(self, "enable_builtin_menu", text="Built-in Menu")
416 layout.prop(self, "enable_debug_mode", text="Debug Mode")
418 layout.separator()
420 layout.prop(
421 self, "conf_uv_sculpt_expanded", text="UV Sculpt",
422 icon='DISCLOSURE_TRI_DOWN' if self.conf_uv_sculpt_expanded
423 else 'DISCLOSURE_TRI_RIGHT')
424 if self.conf_uv_sculpt_expanded:
425 sp = compat.layout_split(layout, 0.05)
426 col = sp.column() # spacer
427 sp = compat.layout_split(sp, 0.3)
428 col = sp.column()
429 col.label(text="Brush Color:")
430 col.prop(self, "uv_sculpt_brush_color", text="")
431 layout.separator()
433 layout.prop(
434 self, "conf_uv_inspection_expanded", text="UV Inspection",
435 icon='DISCLOSURE_TRI_DOWN' if self.conf_uv_inspection_expanded
436 else 'DISCLOSURE_TRI_RIGHT')
437 if self.conf_uv_inspection_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="Overlapped UV Color:")
443 col.prop(self, "uv_inspection_overlapped_color", text="")
444 sp = compat.layout_split(sp, 0.45)
445 col = sp.column()
446 col.label(text="Flipped UV Color:")
447 col.prop(self, "uv_inspection_flipped_color", text="")
449 sp = compat.layout_split(layout, 0.05)
450 col = sp.column() # spacer
451 sp = compat.layout_split(sp, 0.3)
452 col = sp.column()
453 col.label(text="Overlapped UV Color (View3D):")
454 col.prop(self, "uv_inspection_overlapped_color_for_v3d",
455 text="")
456 sp = compat.layout_split(sp, 0.45)
457 col = sp.column()
458 col.label(text="Flipped UV Color (View3D):")
459 col.prop(self, "uv_inspection_flipped_color_for_v3d",
460 text="")
462 layout.separator()
464 layout.prop(
465 self, "conf_texture_projection_expanded",
466 text="Texture Projection",
467 icon='DISCLOSURE_TRI_DOWN'
468 if self.conf_texture_projection_expanded
469 else 'DISCLOSURE_TRI_RIGHT')
470 if self.conf_texture_projection_expanded:
471 sp = compat.layout_split(layout, 0.05)
472 col = sp.column() # spacer
473 sp = compat.layout_split(sp, 0.3)
474 col = sp.column()
475 col.prop(self, "texture_projection_canvas_padding")
476 layout.separator()
478 layout.prop(
479 self, "conf_uv_bounding_box_expanded", text="UV Bounding Box",
480 icon='DISCLOSURE_TRI_DOWN'
481 if self.conf_uv_bounding_box_expanded
482 else 'DISCLOSURE_TRI_RIGHT')
483 if self.conf_uv_bounding_box_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.label(text="Control Point:")
489 col.prop(self, "uv_bounding_box_cp_size")
490 col.prop(self, "uv_bounding_box_cp_react_size")
491 layout.separator()