Merge branch 'master' into blender2.8
[blender.git] / release / scripts / startup / bl_ui / space_view3d_toolbar.py
1 # ##### BEGIN GPL LICENSE BLOCK #####
2 #
3 #  This program is free software; you can redistribute it and/or
4 #  modify it under the terms of the GNU General Public License
5 #  as published by the Free Software Foundation; either version 2
6 #  of the License, or (at your option) any later version.
7 #
8 #  This program is distributed in the hope that it will be useful,
9 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 #  GNU General Public License for more details.
12 #
13 #  You should have received a copy of the GNU General Public License
14 #  along with this program; if not, write to the Free Software Foundation,
15 #  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 #
17 # ##### END GPL LICENSE BLOCK #####
18
19 # <pep8 compliant>
20 import bpy
21 from bpy.types import Menu, Panel, UIList
22 from .properties_grease_pencil_common import (
23     GreasePencilDrawingToolsPanel,
24     GreasePencilStrokeEditPanel,
25     GreasePencilInterpolatePanel,
26     GreasePencilStrokeSculptPanel,
27     GreasePencilBrushPanel,
28     GreasePencilBrushCurvesPanel
29 )
30 from .properties_paint_common import (
31     UnifiedPaintPanel,
32     brush_texture_settings,
33     brush_texpaint_common,
34     brush_mask_texture_settings,
35 )
36
37
38 class View3DPanel:
39     bl_space_type = 'VIEW_3D'
40     bl_region_type = 'TOOLS'
41
42
43 # **************** standard tool clusters ******************
44
45 # Keyframing tools
46 def draw_keyframing_tools(context, layout):
47     col = layout.column(align=True)
48     col.label(text="Keyframes:")
49     row = col.row(align=True)
50     row.operator("anim.keyframe_insert_menu", text="Insert")
51     row.operator("anim.keyframe_delete_v3d", text="Remove")
52
53
54 # Used by vertex & weight paint
55 def draw_vpaint_symmetry(layout, vpaint):
56     col = layout.column(align=True)
57     col.label(text="Mirror:")
58     row = col.row(align=True)
59
60     row.prop(vpaint, "use_symmetry_x", text="X", toggle=True)
61     row.prop(vpaint, "use_symmetry_y", text="Y", toggle=True)
62     row.prop(vpaint, "use_symmetry_z", text="Z", toggle=True)
63
64     col = layout.column()
65     col.prop(vpaint, "radial_symmetry", text="Radial")
66
67
68 # ********** default tools for editmode_mesh ****************
69
70
71 class VIEW3D_PT_tools_meshedit_options(View3DPanel, Panel):
72     bl_category = ""
73     bl_context = ".mesh_edit" # dot on purpose (access from topbar)
74     bl_label = "Mesh Options"
75
76     @classmethod
77     def poll(cls, context):
78         return context.active_object
79
80     def draw(self, context):
81         layout = self.layout
82
83         ob = context.active_object
84
85         tool_settings = context.tool_settings
86         mesh = ob.data
87
88         col = layout.column(align=True)
89         col.prop(mesh, "use_mirror_x")
90
91         row = col.row(align=True)
92         row.active = ob.data.use_mirror_x
93         row.prop(mesh, "use_mirror_topology")
94
95         col = layout.column(align=True)
96         col.label("Edge Select Mode:")
97         col.prop(tool_settings, "edge_path_mode", text="")
98         col.prop(tool_settings, "edge_path_live_unwrap")
99         col.label("Double Threshold:")
100         col.prop(tool_settings, "double_threshold", text="")
101
102 # ********** default tools for editmode_curve ****************
103
104 class VIEW3D_PT_tools_curveedit_options_stroke(View3DPanel, Panel):
105     bl_category = "Options"
106     bl_context = ".curve_edit" # dot on purpose (access from topbar)
107     bl_label = "Curve Stroke"
108
109     def draw(self, context):
110         layout = self.layout
111
112         tool_settings = context.tool_settings
113         cps = tool_settings.curve_paint_settings
114
115         col = layout.column()
116
117         col.prop(cps, "curve_type")
118
119         if cps.curve_type == 'BEZIER':
120             col.label("Bezier Options:")
121             col.prop(cps, "error_threshold")
122             col.prop(cps, "fit_method")
123             col.prop(cps, "use_corners_detect")
124
125             col = layout.column()
126             col.active = cps.use_corners_detect
127             col.prop(cps, "corner_angle")
128
129         col.label("Pressure Radius:")
130         row = layout.row(align=True)
131         rowsub = row.row(align=True)
132         rowsub.prop(cps, "radius_min", text="Min")
133         rowsub.prop(cps, "radius_max", text="Max")
134
135         row.prop(cps, "use_pressure_radius", text="", icon_only=True)
136
137         col = layout.column()
138         col.label("Taper Radius:")
139         row = layout.row(align=True)
140         row.prop(cps, "radius_taper_start", text="Start")
141         row.prop(cps, "radius_taper_end", text="End")
142
143         col = layout.column()
144         col.label("Projection Depth:")
145         row = layout.row(align=True)
146         row.prop(cps, "depth_mode", expand=True)
147
148         col = layout.column()
149         if cps.depth_mode == 'SURFACE':
150             col.prop(cps, "surface_offset")
151             col.prop(cps, "use_offset_absolute")
152             col.prop(cps, "use_stroke_endpoints")
153             if cps.use_stroke_endpoints:
154                 colsub = layout.column(align=True)
155                 colsub.prop(cps, "surface_plane", expand=True)
156
157
158
159
160 # ********** default tools for editmode_armature ****************
161
162
163 class VIEW3D_PT_tools_armatureedit_options(View3DPanel, Panel):
164     bl_category = "Options"
165     bl_context = ".armature_edit"  # dot on purpose (access from topbar)
166     bl_label = "Armature Options"
167
168     def draw(self, context):
169         arm = context.active_object.data
170
171         self.layout.prop(arm, "use_mirror_x")
172
173
174 # ********** default tools for pose-mode ****************
175
176 class VIEW3D_PT_tools_posemode_options(View3DPanel, Panel):
177     bl_category = "Options"
178     bl_context = ".posemode" # dot on purpose (access from topbar)
179     bl_label = "Pose Options"
180
181     def draw(self, context):
182         arm = context.active_object.data
183
184         self.layout.prop(arm, "use_auto_ik")
185         self.layout.prop(arm, "use_mirror_x")
186
187 # ********** default tools for paint modes ****************
188
189
190 class View3DPaintPanel(UnifiedPaintPanel):
191     bl_space_type = 'VIEW_3D'
192     bl_region_type = 'TOOLS'
193
194
195 class VIEW3D_PT_imapaint_tools_missing(Panel, View3DPaintPanel):
196     bl_category = "Tools"
197     bl_context = ".imagepaint" # dot on purpose (access from topbar)
198     bl_label = "Missing Data"
199
200     @classmethod
201     def poll(cls, context):
202         toolsettings = context.tool_settings.image_paint
203         return context.image_paint_object and not toolsettings.detect_data()
204
205     def draw(self, context):
206         layout = self.layout
207         toolsettings = context.tool_settings.image_paint
208
209         col = layout.column()
210         col.label("Missing Data", icon='ERROR')
211         if toolsettings.missing_uvs:
212             col.separator()
213             col.label("Missing UVs", icon='INFO')
214             col.label("Unwrap the mesh in edit mode or generate a simple UV layer")
215             col.operator("paint.add_simple_uvs")
216
217         if toolsettings.mode == 'MATERIAL':
218             if toolsettings.missing_materials:
219                 col.separator()
220                 col.label("Missing Materials", icon='INFO')
221                 col.label("Add a material and paint slot below")
222                 col.operator_menu_enum("paint.add_texture_paint_slot", "type", text="Add Paint Slot")
223             elif toolsettings.missing_texture:
224                 ob = context.active_object
225                 mat = ob.active_material
226
227                 col.separator()
228                 if mat:
229                     col.label("Missing Texture Slots", icon='INFO')
230                     col.label("Add a paint slot below")
231                     col.operator_menu_enum("paint.add_texture_paint_slot", "type", text="Add Paint Slot")
232                 else:
233                     col.label("Missing Materials", icon='INFO')
234                     col.label("Add a material and paint slot below")
235                     col.operator_menu_enum("paint.add_texture_paint_slot", "type", text="Add Paint Slot")
236
237         elif toolsettings.mode == 'IMAGE':
238             if toolsettings.missing_texture:
239                 col.separator()
240                 col.label("Missing Canvas", icon='INFO')
241                 col.label("Add or assign a canvas image below")
242                 col.label("Canvas Image:")
243                 # todo this should be combinded into a single row
244                 col.template_ID(toolsettings, "canvas", open="image.open")
245                 col.operator("image.new", text="New").gen_context = 'PAINT_CANVAS'
246
247         if toolsettings.missing_stencil:
248             col.separator()
249             col.label("Missing Stencil", icon='INFO')
250             col.label("Add or assign a stencil image below")
251             col.label("Stencil Image:")
252             # todo this should be combinded into a single row
253             col.template_ID(toolsettings, "stencil_image", open="image.open")
254             col.operator("image.new", text="New").gen_context = 'PAINT_STENCIL'
255
256
257 class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
258     bl_category = "Tools"
259     bl_context = ".paint_common"  # dot on purpose (access from topbar)
260     bl_label = "Brush"
261
262     @classmethod
263     def poll(cls, context):
264         return cls.paint_settings(context)
265
266     def draw(self, context):
267         layout = self.layout
268
269         toolsettings = context.tool_settings
270         settings = self.paint_settings(context)
271         brush = settings.brush
272
273         if not context.particle_edit_object:
274             col = layout.split().column()
275             col.template_ID_preview(settings, "brush", new="brush.add", rows=3, cols=8)
276
277         # Particle Mode #
278         if context.particle_edit_object:
279             tool = settings.tool
280
281             layout.column().prop(settings, "tool", expand=True)
282
283             if tool != 'NONE':
284                 col = layout.column()
285                 col.prop(brush, "size", slider=True)
286                 if tool != 'ADD':
287                     col.prop(brush, "strength", slider=True)
288
289             if tool == 'ADD':
290                 col.prop(brush, "count")
291                 col = layout.column()
292                 col.prop(settings, "use_default_interpolate")
293                 col.prop(brush, "steps", slider=True)
294                 col.prop(settings, "default_key_count", slider=True)
295             elif tool == 'LENGTH':
296                 layout.row().prop(brush, "length_mode", expand=True)
297             elif tool == 'PUFF':
298                 layout.row().prop(brush, "puff_mode", expand=True)
299                 layout.prop(brush, "use_puff_volume")
300
301         # Sculpt Mode #
302
303         elif context.sculpt_object and brush:
304             capabilities = brush.sculpt_capabilities
305
306             col = layout.column()
307
308             col.separator()
309
310             row = col.row(align=True)
311
312             ups = toolsettings.unified_paint_settings
313             if ((ups.use_unified_size and ups.use_locked_size) or
314                     ((not ups.use_unified_size) and brush.use_locked_size)):
315                 self.prop_unified_size(row, context, brush, "use_locked_size", icon='LOCKED')
316                 self.prop_unified_size(row, context, brush, "unprojected_radius", slider=True, text="Radius")
317             else:
318                 self.prop_unified_size(row, context, brush, "use_locked_size", icon='UNLOCKED')
319                 self.prop_unified_size(row, context, brush, "size", slider=True, text="Radius")
320
321             self.prop_unified_size(row, context, brush, "use_pressure_size")
322
323             # strength, use_strength_pressure, and use_strength_attenuation
324             col.separator()
325             row = col.row(align=True)
326
327             if capabilities.has_space_attenuation:
328                 row.prop(brush, "use_space_attenuation", toggle=True, icon_only=True)
329
330             self.prop_unified_strength(row, context, brush, "strength", text="Strength")
331
332             if capabilities.has_strength_pressure:
333                 self.prop_unified_strength(row, context, brush, "use_pressure_strength")
334
335             # auto_smooth_factor and use_inverse_smooth_pressure
336             if capabilities.has_auto_smooth:
337                 col.separator()
338
339                 row = col.row(align=True)
340                 row.prop(brush, "auto_smooth_factor", slider=True)
341                 row.prop(brush, "use_inverse_smooth_pressure", toggle=True, text="")
342
343             # normal_weight
344             if capabilities.has_normal_weight:
345                 col.separator()
346                 row = col.row(align=True)
347                 row.prop(brush, "normal_weight", slider=True)
348
349             # crease_pinch_factor
350             if capabilities.has_pinch_factor:
351                 col.separator()
352                 row = col.row(align=True)
353                 row.prop(brush, "crease_pinch_factor", slider=True, text="Pinch")
354
355             # rake_factor
356             if capabilities.has_rake_factor:
357                 col.separator()
358                 row = col.row(align=True)
359                 row.prop(brush, "rake_factor", slider=True)
360
361             # use_original_normal and sculpt_plane
362             if capabilities.has_sculpt_plane:
363                 col.separator()
364                 row = col.row(align=True)
365
366                 row.prop(brush, "use_original_normal", toggle=True, icon_only=True)
367
368                 row.prop(brush, "sculpt_plane", text="")
369
370             if brush.sculpt_tool == 'MASK':
371                 col.prop(brush, "mask_tool", text="")
372
373             # plane_offset, use_offset_pressure, use_plane_trim, plane_trim
374             if capabilities.has_plane_offset:
375                 row = col.row(align=True)
376                 row.prop(brush, "plane_offset", slider=True)
377                 row.prop(brush, "use_offset_pressure", text="")
378
379                 col.separator()
380
381                 row = col.row()
382                 row.prop(brush, "use_plane_trim", text="Trim")
383                 row = col.row()
384                 row.active = brush.use_plane_trim
385                 row.prop(brush, "plane_trim", slider=True, text="Distance")
386
387             # height
388             if capabilities.has_height:
389                 row = col.row()
390                 row.prop(brush, "height", slider=True, text="Height")
391
392             # use_frontface
393             col.separator()
394             col.prop(brush, "use_frontface", text="Front Faces Only")
395             col.prop(brush, "use_projected")
396
397             # direction
398             col.separator()
399             col.row().prop(brush, "direction", expand=True)
400
401             # use_accumulate
402             if capabilities.has_accumulate:
403                 col.separator()
404
405                 col.prop(brush, "use_accumulate")
406
407             # use_persistent, set_persistent_base
408             if capabilities.has_persistence:
409                 col.separator()
410
411                 ob = context.sculpt_object
412                 do_persistent = True
413
414                 # not supported yet for this case
415                 for md in ob.modifiers:
416                     if md.type == 'MULTIRES':
417                         do_persistent = False
418                         break
419
420                 if do_persistent:
421                     col.prop(brush, "use_persistent")
422                     col.operator("sculpt.set_persistent_base")
423
424         # Texture Paint Mode #
425
426         elif context.image_paint_object and brush:
427             brush_texpaint_common(self, context, layout, brush, settings, True)
428
429         # Weight Paint Mode #
430         elif context.weight_paint_object and brush:
431
432             col = layout.column()
433
434             row = col.row(align=True)
435             self.prop_unified_weight(row, context, brush, "weight", slider=True, text="Weight")
436
437             row = col.row(align=True)
438             self.prop_unified_size(row, context, brush, "size", slider=True, text="Radius")
439             self.prop_unified_size(row, context, brush, "use_pressure_size")
440
441             row = col.row(align=True)
442             self.prop_unified_strength(row, context, brush, "strength", text="Strength")
443             self.prop_unified_strength(row, context, brush, "use_pressure_strength")
444
445             col.separator()
446             col.prop(brush, "vertex_tool", text="Blend")
447
448             if brush.vertex_tool != 'SMEAR':
449                 col.prop(brush, "use_accumulate")
450                 col.separator()
451
452             col.prop(brush, "use_frontface", text="Front Faces Only")
453             row = col.row()
454             row.prop(brush, "use_frontface_falloff", text="Falloff Angle")
455             sub = row.row()
456             sub.active = brush.use_frontface_falloff
457             sub.prop(brush, "falloff_angle", text="")
458
459             col.prop(brush, "use_projected")
460
461             col = layout.column()
462             col.prop(toolsettings, "use_auto_normalize", text="Auto Normalize")
463             col.prop(toolsettings, "use_multipaint", text="Multi-Paint")
464
465         # Vertex Paint Mode #
466         elif context.vertex_paint_object and brush:
467             col = layout.column()
468             self.prop_unified_color_picker(col, context, brush, "color", value_slider=True)
469             if settings.palette:
470                 col.template_palette(settings, "palette", color=True)
471             row = col.row(align=True)
472             self.prop_unified_color(row, context, brush, "color", text="")
473             self.prop_unified_color(row, context, brush, "secondary_color", text="")
474             row.separator()
475             row.operator("paint.brush_colors_flip", icon='FILE_REFRESH', text="")
476
477             col.separator()
478             row = col.row(align=True)
479             self.prop_unified_size(row, context, brush, "size", slider=True, text="Radius")
480             self.prop_unified_size(row, context, brush, "use_pressure_size")
481
482             row = col.row(align=True)
483             self.prop_unified_strength(row, context, brush, "strength", text="Strength")
484             self.prop_unified_strength(row, context, brush, "use_pressure_strength")
485
486             col.separator()
487             col.prop(brush, "vertex_tool", text="Blend")
488             col.prop(brush, "use_alpha")
489
490             if brush.vertex_tool != 'SMEAR':
491                 col.prop(brush, "use_accumulate")
492                 col.separator()
493
494             col.prop(brush, "use_frontface", text="Front Faces Only")
495             row = col.row()
496             row.prop(brush, "use_frontface_falloff", text="Falloff Angle")
497             sub = row.row()
498             sub.active = brush.use_frontface_falloff
499             sub.prop(brush, "falloff_angle", text="")
500
501             col.prop(brush, "use_projected")
502
503             col.separator()
504             col.template_ID(settings, "palette", new="palette.new")
505
506
507 class TEXTURE_UL_texpaintslots(UIList):
508     def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
509         mat = data
510
511         if self.layout_type in {'DEFAULT', 'COMPACT'}:
512             layout.prop(item, "name", text="", emboss=False, icon_value=icon)
513         elif self.layout_type == 'GRID':
514             layout.alignment = 'CENTER'
515             layout.label(text="")
516
517
518 class VIEW3D_MT_tools_projectpaint_uvlayer(Menu):
519     bl_label = "Clone Layer"
520
521     def draw(self, context):
522         layout = self.layout
523
524         for i, uv_layer in enumerate(context.active_object.data.uv_layers):
525             props = layout.operator("wm.context_set_int", text=uv_layer.name, translate=False)
526             props.data_path = "active_object.data.uv_layers.active_index"
527             props.value = i
528
529
530 class VIEW3D_PT_slots_projectpaint(View3DPanel, Panel):
531     bl_context = ".imagepaint" # dot on purpose (access from topbar)
532     bl_label = "Slots"
533     bl_category = "Slots"
534
535     @classmethod
536     def poll(cls, context):
537         brush = context.tool_settings.image_paint.brush
538         ob = context.active_object
539         return (brush is not None and ob is not None)
540
541     def draw(self, context):
542         layout = self.layout
543
544         settings = context.tool_settings.image_paint
545         # brush = settings.brush
546
547         ob = context.active_object
548         col = layout.column()
549
550         col.label("Painting Mode:")
551         col.prop(settings, "mode", text="")
552         col.separator()
553
554         if settings.mode == 'MATERIAL':
555             if len(ob.material_slots) > 1:
556                 col.label("Materials:")
557                 col.template_list("MATERIAL_UL_matslots", "layers",
558                                   ob, "material_slots",
559                                   ob, "active_material_index", rows=2)
560
561             mat = ob.active_material
562             if mat:
563                 col.label("Available Paint Slots:")
564                 col.template_list("TEXTURE_UL_texpaintslots", "",
565                                   mat, "texture_paint_images",
566                                   mat, "paint_active_slot", rows=2)
567
568                 if mat.texture_paint_slots:
569                     slot = mat.texture_paint_slots[mat.paint_active_slot]
570                 else:
571                     slot = None
572
573                 if slot and slot.is_valid:
574                     col.label("UV Map:")
575                     col.prop_search(slot, "uv_layer", ob.data, "uv_layers", text="")
576
577         elif settings.mode == 'IMAGE':
578             mesh = ob.data
579             uv_text = mesh.uv_layers.active.name if mesh.uv_layers.active else ""
580             col.label("Canvas Image:")
581             # todo this should be combinded into a single row
582             col.template_ID(settings, "canvas", open="image.open")
583             col.operator("image.new", text="New").gen_context = 'PAINT_CANVAS'
584             col.label("UV Map:")
585             col.menu("VIEW3D_MT_tools_projectpaint_uvlayer", text=uv_text, translate=False)
586
587         col.separator()
588         col.operator("image.save_dirty", text="Save All Images")
589
590
591 class VIEW3D_PT_stencil_projectpaint(View3DPanel, Panel):
592     bl_context = ".imagepaint" # dot on purpose (access from topbar)
593     bl_label = "Mask"
594     bl_category = "Slots"
595
596     @classmethod
597     def poll(cls, context):
598         brush = context.tool_settings.image_paint.brush
599         ob = context.active_object
600         return (brush is not None and ob is not None)
601
602     def draw_header(self, context):
603         ipaint = context.tool_settings.image_paint
604         self.layout.prop(ipaint, "use_stencil_layer", text="")
605
606     def draw(self, context):
607         layout = self.layout
608
609         toolsettings = context.tool_settings
610         ipaint = toolsettings.image_paint
611         ob = context.active_object
612         mesh = ob.data
613
614         col = layout.column()
615         col.active = ipaint.use_stencil_layer
616
617         stencil_text = mesh.uv_layer_stencil.name if mesh.uv_layer_stencil else ""
618         col.label("UV Map")
619         col.menu("VIEW3D_MT_tools_projectpaint_stencil", text=stencil_text, translate=False)
620
621         col.label("Stencil Image:")
622         # todo this should be combinded into a single row
623         col.template_ID(ipaint, "stencil_image", open="image.open")
624         col.operator("image.new", text="New").gen_context = 'PAINT_STENCIL'
625
626         col.label("Visualization:")
627         row = col.row(align=True)
628         row.prop(ipaint, "stencil_color", text="")
629         row.prop(ipaint, "invert_stencil", text="", icon='IMAGE_ALPHA')
630
631
632 class VIEW3D_PT_tools_brush_overlay(Panel, View3DPaintPanel):
633     bl_category = "Options"
634     bl_context = ".paint_common"  # dot on purpose (access from topbar)
635     bl_label = "Overlay"
636
637     @classmethod
638     def poll(cls, context):
639         settings = cls.paint_settings(context)
640         return (settings and
641                 settings.brush and
642                 (context.sculpt_object or
643                  context.vertex_paint_object or
644                  context.weight_paint_object or
645                  context.image_paint_object))
646
647     def draw(self, context):
648         layout = self.layout
649
650         settings = self.paint_settings(context)
651         brush = settings.brush
652         tex_slot = brush.texture_slot
653         tex_slot_mask = brush.mask_texture_slot
654
655         col = layout.column()
656
657         col.label(text="Curve:")
658
659         row = col.row(align=True)
660         if brush.use_cursor_overlay:
661             row.prop(brush, "use_cursor_overlay", toggle=True, text="", icon='RESTRICT_VIEW_OFF')
662         else:
663             row.prop(brush, "use_cursor_overlay", toggle=True, text="", icon='RESTRICT_VIEW_ON')
664
665         sub = row.row(align=True)
666         sub.prop(brush, "cursor_overlay_alpha", text="Alpha")
667         sub.prop(brush, "use_cursor_overlay_override", toggle=True, text="", icon='BRUSH_DATA')
668
669         col.active = brush.brush_capabilities.has_overlay
670
671         if context.image_paint_object or context.sculpt_object or context.vertex_paint_object:
672             col.label(text="Texture:")
673             row = col.row(align=True)
674             if tex_slot.map_mode != 'STENCIL':
675                 if brush.use_primary_overlay:
676                     row.prop(brush, "use_primary_overlay", toggle=True, text="", icon='RESTRICT_VIEW_OFF')
677                 else:
678                     row.prop(brush, "use_primary_overlay", toggle=True, text="", icon='RESTRICT_VIEW_ON')
679
680             sub = row.row(align=True)
681             sub.prop(brush, "texture_overlay_alpha", text="Alpha")
682             sub.prop(brush, "use_primary_overlay_override", toggle=True, text="", icon='BRUSH_DATA')
683
684         if context.image_paint_object:
685             col.label(text="Mask Texture:")
686
687             row = col.row(align=True)
688             if tex_slot_mask.map_mode != 'STENCIL':
689                 if brush.use_secondary_overlay:
690                     row.prop(brush, "use_secondary_overlay", toggle=True, text="", icon='RESTRICT_VIEW_OFF')
691                 else:
692                     row.prop(brush, "use_secondary_overlay", toggle=True, text="", icon='RESTRICT_VIEW_ON')
693
694             sub = row.row(align=True)
695             sub.prop(brush, "mask_overlay_alpha", text="Alpha")
696             sub.prop(brush, "use_secondary_overlay_override", toggle=True, text="", icon='BRUSH_DATA')
697
698
699 class VIEW3D_PT_tools_brush_texture(Panel, View3DPaintPanel):
700     bl_category = "Tools"
701     bl_context = ".paint_common"  # dot on purpose (access from topbar)
702     bl_label = "Texture"
703     bl_options = {'DEFAULT_CLOSED'}
704
705     @classmethod
706     def poll(cls, context):
707         settings = cls.paint_settings(context)
708         return (settings and settings.brush and
709                 (context.sculpt_object or context.image_paint_object or context.vertex_paint_object))
710
711     def draw(self, context):
712         layout = self.layout
713
714         settings = self.paint_settings(context)
715         brush = settings.brush
716
717         col = layout.column()
718
719         col.template_ID_preview(brush, "texture", new="texture.new", rows=3, cols=8)
720
721         brush_texture_settings(col, brush, context.sculpt_object)
722
723
724 class VIEW3D_PT_tools_mask_texture(Panel, View3DPaintPanel):
725     bl_category = "Tools"
726     bl_context = ".imagepaint" # dot on purpose (access from topbar)
727     bl_label = "Texture Mask"
728     bl_options = {'DEFAULT_CLOSED'}
729
730     @classmethod
731     def poll(cls, context):
732         settings = cls.paint_settings(context)
733         return (settings and settings.brush and context.image_paint_object)
734
735     def draw(self, context):
736         layout = self.layout
737
738         brush = context.tool_settings.image_paint.brush
739
740         col = layout.column()
741
742         col.template_ID_preview(brush, "mask_texture", new="texture.new", rows=3, cols=8)
743
744         brush_mask_texture_settings(col, brush)
745
746
747 class VIEW3D_PT_tools_brush_stroke(Panel, View3DPaintPanel):
748     bl_category = "Tools"
749     bl_context = ".paint_common"  # dot on purpose (access from topbar)
750     bl_label = "Stroke"
751     bl_options = {'DEFAULT_CLOSED'}
752
753     @classmethod
754     def poll(cls, context):
755         settings = cls.paint_settings(context)
756         return (settings and
757                 settings.brush and
758                 (context.sculpt_object or
759                  context.vertex_paint_object or
760                  context.weight_paint_object or
761                  context.image_paint_object))
762
763     def draw(self, context):
764         layout = self.layout
765
766         settings = self.paint_settings(context)
767         brush = settings.brush
768
769         col = layout.column()
770
771         col.label(text="Stroke Method:")
772
773         col.prop(brush, "stroke_method", text="")
774
775         if brush.use_anchor:
776             col.separator()
777             col.prop(brush, "use_edge_to_edge", "Edge To Edge")
778
779         if brush.use_airbrush:
780             col.separator()
781             col.prop(brush, "rate", text="Rate", slider=True)
782
783         if brush.use_space:
784             col.separator()
785             row = col.row(align=True)
786             row.prop(brush, "spacing", text="Spacing")
787             row.prop(brush, "use_pressure_spacing", toggle=True, text="")
788
789         if brush.use_line or brush.use_curve:
790             col.separator()
791             row = col.row(align=True)
792             row.prop(brush, "spacing", text="Spacing")
793
794         if brush.use_curve:
795             col.separator()
796             col.template_ID(brush, "paint_curve", new="paintcurve.new")
797             col.operator("paintcurve.draw")
798
799         if context.sculpt_object:
800             if brush.sculpt_capabilities.has_jitter:
801                 col.separator()
802
803                 row = col.row(align=True)
804                 row.prop(brush, "use_relative_jitter", icon_only=True)
805                 if brush.use_relative_jitter:
806                     row.prop(brush, "jitter", slider=True)
807                 else:
808                     row.prop(brush, "jitter_absolute")
809                 row.prop(brush, "use_pressure_jitter", toggle=True, text="")
810
811             if brush.sculpt_capabilities.has_smooth_stroke:
812                 col = layout.column()
813                 col.separator()
814
815                 col.prop(brush, "use_smooth_stroke")
816
817                 sub = col.column()
818                 sub.active = brush.use_smooth_stroke
819                 sub.prop(brush, "smooth_stroke_radius", text="Radius", slider=True)
820                 sub.prop(brush, "smooth_stroke_factor", text="Factor", slider=True)
821         else:
822             col.separator()
823
824             row = col.row(align=True)
825             row.prop(brush, "use_relative_jitter", icon_only=True)
826             if brush.use_relative_jitter:
827                 row.prop(brush, "jitter", slider=True)
828             else:
829                 row.prop(brush, "jitter_absolute")
830             row.prop(brush, "use_pressure_jitter", toggle=True, text="")
831
832             col = layout.column()
833             col.separator()
834
835             if brush.brush_capabilities.has_smooth_stroke:
836                 col.prop(brush, "use_smooth_stroke")
837
838                 sub = col.column()
839                 sub.active = brush.use_smooth_stroke
840                 sub.prop(brush, "smooth_stroke_radius", text="Radius", slider=True)
841                 sub.prop(brush, "smooth_stroke_factor", text="Factor", slider=True)
842
843         layout.prop(settings, "input_samples")
844
845
846 class VIEW3D_PT_tools_brush_curve(Panel, View3DPaintPanel):
847     bl_category = "Tools"
848     bl_context = ".paint_common"  # dot on purpose (access from topbar)
849     bl_label = "Curve"
850     bl_options = {'DEFAULT_CLOSED'}
851
852     @classmethod
853     def poll(cls, context):
854         settings = cls.paint_settings(context)
855         return (settings and settings.brush and settings.brush.curve)
856
857     def draw(self, context):
858         layout = self.layout
859
860         settings = self.paint_settings(context)
861
862         brush = settings.brush
863
864         layout.template_curve_mapping(brush, "curve", brush=True)
865
866         col = layout.column(align=True)
867         row = col.row(align=True)
868         row.operator("brush.curve_preset", icon='SMOOTHCURVE', text="").shape = 'SMOOTH'
869         row.operator("brush.curve_preset", icon='SPHERECURVE', text="").shape = 'ROUND'
870         row.operator("brush.curve_preset", icon='ROOTCURVE', text="").shape = 'ROOT'
871         row.operator("brush.curve_preset", icon='SHARPCURVE', text="").shape = 'SHARP'
872         row.operator("brush.curve_preset", icon='LINCURVE', text="").shape = 'LINE'
873         row.operator("brush.curve_preset", icon='NOCURVE', text="").shape = 'MAX'
874
875
876 class VIEW3D_PT_sculpt_dyntopo(Panel, View3DPaintPanel):
877     bl_category = "Tools"
878     bl_context = ".sculpt_mode"  # dot on purpose (access from topbar)
879     bl_label = "Dyntopo"
880     bl_options = {'DEFAULT_CLOSED'}
881
882     @classmethod
883     def poll(cls, context):
884         return (context.sculpt_object and context.tool_settings.sculpt)
885
886     def draw_header(self, context):
887         layout = self.layout
888         layout.operator(
889                 "sculpt.dynamic_topology_toggle",
890                 icon='CHECKBOX_HLT' if context.sculpt_object.use_dynamic_topology_sculpting else 'CHECKBOX_DEHLT',
891                 text="",
892                 emboss=False,
893                 )
894
895     def draw(self, context):
896         layout = self.layout
897
898         toolsettings = context.tool_settings
899         sculpt = toolsettings.sculpt
900         settings = self.paint_settings(context)
901         brush = settings.brush
902
903         col = layout.column()
904         col.active = context.sculpt_object.use_dynamic_topology_sculpting
905         sub = col.column(align=True)
906         sub.active = (brush and brush.sculpt_tool != 'MASK')
907         if (sculpt.detail_type_method == 'CONSTANT'):
908             row = sub.row(align=True)
909             row.prop(sculpt, "constant_detail_resolution")
910             row.operator("sculpt.sample_detail_size", text="", icon='EYEDROPPER')
911         elif (sculpt.detail_type_method == 'BRUSH'):
912             sub.prop(sculpt, "detail_percent")
913         else:
914             sub.prop(sculpt, "detail_size")
915         sub.prop(sculpt, "detail_refine_method", text="")
916         sub.prop(sculpt, "detail_type_method", text="")
917         col.separator()
918         col.prop(sculpt, "use_smooth_shading")
919         col.operator("sculpt.optimize")
920         if (sculpt.detail_type_method == 'CONSTANT'):
921             col.operator("sculpt.detail_flood_fill")
922         col.separator()
923         col.prop(sculpt, "symmetrize_direction")
924         col.operator("sculpt.symmetrize")
925
926
927 class VIEW3D_PT_sculpt_options(Panel, View3DPaintPanel):
928     bl_category = "Options"
929     bl_context = ".sculpt_mode"  # dot on purpose (access from topbar)
930     bl_label = "Options"
931     bl_options = {'DEFAULT_CLOSED'}
932
933     @classmethod
934     def poll(cls, context):
935         return (context.sculpt_object and context.tool_settings.sculpt)
936
937     def draw(self, context):
938         layout = self.layout
939         # scene = context.scene
940
941         toolsettings = context.tool_settings
942         sculpt = toolsettings.sculpt
943         capabilities = sculpt.brush.sculpt_capabilities
944
945         col = layout.column(align=True)
946         col.active = capabilities.has_gravity
947         col.label(text="Gravity:")
948         col.prop(sculpt, "gravity", slider=True, text="Factor")
949         col.prop(sculpt, "gravity_object")
950         col.separator()
951
952         layout.prop(sculpt, "use_threaded", text="Threaded Sculpt")
953         layout.prop(sculpt, "show_low_resolution")
954         layout.prop(sculpt, "use_deform_only")
955         layout.prop(sculpt, "show_diffuse_color")
956         layout.prop(sculpt, "show_mask")
957
958         self.unified_paint_settings(layout, context)
959
960
961 class VIEW3D_PT_sculpt_symmetry(Panel, View3DPaintPanel):
962     bl_category = "Tools"
963     bl_context = ".sculpt_mode"  # dot on purpose (access from topbar)
964     bl_label = "Symmetry/Lock"
965     bl_options = {'DEFAULT_CLOSED'}
966
967     @classmethod
968     def poll(cls, context):
969         return (context.sculpt_object and context.tool_settings.sculpt)
970
971     def draw(self, context):
972         layout = self.layout
973
974         sculpt = context.tool_settings.sculpt
975
976         col = layout.column(align=True)
977         col.label(text="Mirror:")
978         row = col.row(align=True)
979         row.prop(sculpt, "use_symmetry_x", text="X", toggle=True)
980         row.prop(sculpt, "use_symmetry_y", text="Y", toggle=True)
981         row.prop(sculpt, "use_symmetry_z", text="Z", toggle=True)
982
983         layout.column().prop(sculpt, "radial_symmetry", text="Radial")
984         layout.prop(sculpt, "use_symmetry_feather", text="Feather")
985
986         layout.label(text="Lock:")
987
988         row = layout.row(align=True)
989         row.prop(sculpt, "lock_x", text="X", toggle=True)
990         row.prop(sculpt, "lock_y", text="Y", toggle=True)
991         row.prop(sculpt, "lock_z", text="Z", toggle=True)
992
993         layout.label(text="Tiling:")
994
995         row = layout.row(align=True)
996         row.prop(sculpt, "tile_x", text="X", toggle=True)
997         row.prop(sculpt, "tile_y", text="Y", toggle=True)
998         row.prop(sculpt, "tile_z", text="Z", toggle=True)
999
1000         layout.column().prop(sculpt, "tile_offset", text="Tile Offset")
1001
1002
1003 class VIEW3D_PT_tools_brush_appearance(Panel, View3DPaintPanel):
1004     bl_category = "Options"
1005     bl_context = ".paint_common"  # dot on purpose (access from topbar)
1006     bl_label = "Appearance"
1007
1008     @classmethod
1009     def poll(cls, context):
1010         settings = cls.paint_settings(context)
1011         return (settings is not None) and (not isinstance(settings, bpy.types.ParticleEdit))
1012
1013     def draw(self, context):
1014         layout = self.layout
1015
1016         settings = self.paint_settings(context)
1017         brush = settings.brush
1018
1019         if brush is None:  # unlikely but can happen
1020             layout.label(text="Brush Unset")
1021             return
1022
1023         col = layout.column()
1024         col.prop(settings, "show_brush")
1025
1026         sub = col.column()
1027         sub.active = settings.show_brush
1028
1029         if context.sculpt_object and context.tool_settings.sculpt:
1030             if brush.sculpt_capabilities.has_secondary_color:
1031                 sub.row().prop(brush, "cursor_color_add", text="Add")
1032                 sub.row().prop(brush, "cursor_color_subtract", text="Subtract")
1033             else:
1034                 sub.prop(brush, "cursor_color_add", text="")
1035         else:
1036             sub.prop(brush, "cursor_color_add", text="")
1037
1038         col.separator()
1039
1040         col = col.column(align=True)
1041         col.prop(brush, "use_custom_icon")
1042         sub = col.column()
1043         sub.active = brush.use_custom_icon
1044         sub.prop(brush, "icon_filepath", text="")
1045
1046 # ********** default tools for weight-paint ****************
1047
1048
1049 class VIEW3D_PT_tools_weightpaint_symmetry(Panel, View3DPaintPanel):
1050     bl_category = "Tools"
1051     bl_context = ".weightpaint"
1052     bl_options = {'DEFAULT_CLOSED'}
1053     bl_label = "Symmetry"
1054
1055     def draw(self, context):
1056         layout = self.layout
1057         toolsettings = context.tool_settings
1058         wpaint = toolsettings.weight_paint
1059         draw_vpaint_symmetry(layout, wpaint)
1060
1061
1062 class VIEW3D_PT_tools_weightpaint_options(Panel, View3DPaintPanel):
1063     bl_category = "Options"
1064     bl_context = ".weightpaint"
1065     bl_label = "Options"
1066
1067     def draw(self, context):
1068         layout = self.layout
1069
1070         tool_settings = context.tool_settings
1071         wpaint = tool_settings.weight_paint
1072
1073         col = layout.column()
1074         col.prop(wpaint, "use_group_restrict")
1075
1076         obj = context.weight_paint_object
1077         if obj.type == 'MESH':
1078             mesh = obj.data
1079             col.prop(mesh, "use_mirror_x")
1080             row = col.row()
1081             row.active = mesh.use_mirror_x
1082             row.prop(mesh, "use_mirror_topology")
1083
1084         col.label("Show Zero Weights:")
1085         sub = col.row()
1086         sub.prop(tool_settings, "vertex_group_user", expand=True)
1087
1088         self.unified_paint_settings(col, context)
1089
1090 # ********** default tools for vertex-paint ****************
1091
1092
1093 class VIEW3D_PT_tools_vertexpaint(Panel, View3DPaintPanel):
1094     bl_category = "Options"
1095     bl_context = ".vertexpaint"  # dot on purpose (access from topbar)
1096     bl_label = "Options"
1097
1098     def draw(self, context):
1099         layout = self.layout
1100
1101         toolsettings = context.tool_settings
1102         vpaint = toolsettings.vertex_paint
1103
1104         col = layout.column()
1105
1106         self.unified_paint_settings(col, context)
1107
1108
1109 class VIEW3D_PT_tools_vertexpaint_symmetry(Panel, View3DPaintPanel):
1110     bl_category = "Tools"
1111     bl_context = ".vertexpaint"  # dot on purpose (access from topbar)
1112     bl_options = {'DEFAULT_CLOSED'}
1113     bl_label = "Symmetry"
1114
1115     def draw(self, context):
1116         layout = self.layout
1117         toolsettings = context.tool_settings
1118         vpaint = toolsettings.vertex_paint
1119         draw_vpaint_symmetry(layout, vpaint)
1120
1121
1122 # ********** default tools for texture-paint ****************
1123
1124
1125 class VIEW3D_PT_tools_imagepaint_external(Panel, View3DPaintPanel):
1126     bl_category = "Tools"
1127     bl_context = ".imagepaint" # dot on purpose (access from topbar)
1128     bl_label = "External"
1129     bl_options = {'DEFAULT_CLOSED'}
1130
1131     def draw(self, context):
1132         layout = self.layout
1133
1134         toolsettings = context.tool_settings
1135         ipaint = toolsettings.image_paint
1136
1137         col = layout.column()
1138         row = col.split(align=True, percentage=0.55)
1139         row.operator("image.project_edit", text="Quick Edit")
1140         row.operator("image.project_apply", text="Apply")
1141
1142         col.row().prop(ipaint, "screen_grab_size", text="")
1143
1144         col.operator("paint.project_image", text="Apply Camera Image")
1145
1146
1147 class VIEW3D_PT_tools_imagepaint_symmetry(Panel, View3DPaintPanel):
1148     bl_category = "Tools"
1149     bl_context = ".imagepaint" # dot on purpose (access from topbar)
1150     bl_label = "Symmetry"
1151     bl_options = {'DEFAULT_CLOSED'}
1152
1153     def draw(self, context):
1154         layout = self.layout
1155
1156         toolsettings = context.tool_settings
1157         ipaint = toolsettings.image_paint
1158
1159         col = layout.column(align=True)
1160         row = col.row(align=True)
1161         row.prop(ipaint, "use_symmetry_x", text="X", toggle=True)
1162         row.prop(ipaint, "use_symmetry_y", text="Y", toggle=True)
1163         row.prop(ipaint, "use_symmetry_z", text="Z", toggle=True)
1164
1165
1166 class VIEW3D_PT_tools_projectpaint(View3DPaintPanel, Panel):
1167     bl_category = "Options"
1168     bl_context = ".imagepaint" # dot on purpose (access from topbar)
1169     bl_label = "Project Paint"
1170
1171     @classmethod
1172     def poll(cls, context):
1173         brush = context.tool_settings.image_paint.brush
1174         return (brush is not None)
1175
1176     def draw(self, context):
1177         layout = self.layout
1178
1179         toolsettings = context.tool_settings
1180         ipaint = toolsettings.image_paint
1181
1182         col = layout.column()
1183
1184         col.prop(ipaint, "use_occlude")
1185         col.prop(ipaint, "use_backface_culling")
1186
1187         row = layout.row()
1188         row.prop(ipaint, "use_normal_falloff")
1189
1190         sub = row.row()
1191         sub.active = (ipaint.use_normal_falloff)
1192         sub.prop(ipaint, "normal_angle", text="")
1193
1194         layout.prop(ipaint, "use_cavity")
1195         if ipaint.use_cavity:
1196             layout.template_curve_mapping(ipaint, "cavity_curve", brush=True)
1197
1198         layout.prop(ipaint, "seam_bleed")
1199         layout.prop(ipaint, "dither")
1200         self.unified_paint_settings(layout, context)
1201
1202
1203 class VIEW3D_PT_imagepaint_options(View3DPaintPanel):
1204     bl_category = "Options"
1205     bl_label = "Options"
1206
1207     @classmethod
1208     def poll(cls, context):
1209         return (context.image_paint_object and context.tool_settings.image_paint)
1210
1211     def draw(self, context):
1212         layout = self.layout
1213
1214         col = layout.column()
1215         self.unified_paint_settings(col, context)
1216
1217
1218 class VIEW3D_MT_tools_projectpaint_stencil(Menu):
1219     bl_label = "Mask Layer"
1220
1221     def draw(self, context):
1222         layout = self.layout
1223         for i, uv_layer in enumerate(context.active_object.data.uv_layers):
1224             props = layout.operator("wm.context_set_int", text=uv_layer.name, translate=False)
1225             props.data_path = "active_object.data.uv_layer_stencil_index"
1226             props.value = i
1227
1228
1229 class VIEW3D_PT_tools_particlemode(View3DPanel, Panel):
1230     """Default tools for particle mode"""
1231     bl_context = ".particlemode"
1232     bl_label = "Options"
1233     bl_category = "Tools"
1234
1235     def draw(self, context):
1236         layout = self.layout
1237
1238         pe = context.tool_settings.particle_edit
1239         ob = pe.object
1240
1241         layout.prop(pe, "type", text="")
1242
1243         ptcache = None
1244
1245         if pe.type == 'PARTICLES':
1246             if ob.particle_systems:
1247                 if len(ob.particle_systems) > 1:
1248                     layout.template_list("UI_UL_list", "particle_systems", ob, "particle_systems",
1249                                          ob.particle_systems, "active_index", rows=2, maxrows=3)
1250
1251                 ptcache = ob.particle_systems.active.point_cache
1252         else:
1253             for md in ob.modifiers:
1254                 if md.type == pe.type:
1255                     ptcache = md.point_cache
1256
1257         if ptcache and len(ptcache.point_caches) > 1:
1258             layout.template_list("UI_UL_list", "particles_point_caches", ptcache, "point_caches",
1259                                  ptcache.point_caches, "active_index", rows=2, maxrows=3)
1260
1261         if not pe.is_editable:
1262             layout.label(text="Point cache must be baked")
1263             layout.label(text="in memory to enable editing!")
1264
1265         col = layout.column(align=True)
1266         if pe.is_hair:
1267             col.active = pe.is_editable
1268             col.prop(pe, "use_emitter_deflect", text="Deflect Emitter")
1269             sub = col.row(align=True)
1270             sub.active = pe.use_emitter_deflect
1271             sub.prop(pe, "emitter_distance", text="Distance")
1272
1273         col = layout.column(align=True)
1274         col.active = pe.is_editable
1275         col.label(text="Keep:")
1276         col.prop(pe, "use_preserve_length", text="Lengths")
1277         col.prop(pe, "use_preserve_root", text="Root")
1278         if not pe.is_hair:
1279             col.label(text="Correct:")
1280             col.prop(pe, "use_auto_velocity", text="Velocity")
1281         col.prop(ob.data, "use_mirror_x")
1282
1283         col.prop(pe, "shape_object")
1284         col.operator("particle.shape_cut")
1285
1286         col = layout.column(align=True)
1287         col.active = pe.is_editable
1288         col.label(text="Draw:")
1289         col.prop(pe, "draw_step", text="Path Steps")
1290         if pe.is_hair:
1291             col.prop(pe, "show_particles", text="Children")
1292         else:
1293             if pe.type == 'PARTICLES':
1294                 col.prop(pe, "show_particles", text="Particles")
1295             col.prop(pe, "use_fade_time")
1296             sub = col.row(align=True)
1297             sub.active = pe.use_fade_time
1298             sub.prop(pe, "fade_frames", slider=True)
1299
1300
1301 # Grease Pencil drawing tools
1302 class VIEW3D_PT_tools_grease_pencil_draw(GreasePencilDrawingToolsPanel, Panel):
1303     bl_space_type = 'VIEW_3D'
1304
1305
1306 # Grease Pencil stroke editing tools
1307 class VIEW3D_PT_tools_grease_pencil_edit(GreasePencilStrokeEditPanel, Panel):
1308     bl_space_type = 'VIEW_3D'
1309
1310
1311 # Grease Pencil stroke interpolation tools
1312 class VIEW3D_PT_tools_grease_pencil_interpolate(GreasePencilInterpolatePanel, Panel):
1313     bl_space_type = 'VIEW_3D'
1314
1315
1316 # Grease Pencil stroke sculpting tools
1317 class VIEW3D_PT_tools_grease_pencil_sculpt(GreasePencilStrokeSculptPanel, Panel):
1318     bl_space_type = 'VIEW_3D'
1319
1320
1321 # Grease Pencil drawing brushes
1322 class VIEW3D_PT_tools_grease_pencil_brush(GreasePencilBrushPanel, Panel):
1323     bl_space_type = 'VIEW_3D'
1324
1325 # Grease Pencil drawingcurves
1326 class VIEW3D_PT_tools_grease_pencil_brushcurves(GreasePencilBrushCurvesPanel, Panel):
1327     bl_space_type = 'VIEW_3D'
1328
1329
1330 classes = (
1331     VIEW3D_PT_tools_meshedit_options,
1332     VIEW3D_PT_tools_curveedit_options_stroke,
1333     VIEW3D_PT_tools_armatureedit_options,
1334     VIEW3D_PT_tools_posemode_options,
1335     VIEW3D_PT_imapaint_tools_missing,
1336     VIEW3D_PT_tools_brush,
1337     TEXTURE_UL_texpaintslots,
1338     VIEW3D_MT_tools_projectpaint_uvlayer,
1339     VIEW3D_PT_slots_projectpaint,
1340     VIEW3D_PT_stencil_projectpaint,
1341     VIEW3D_PT_tools_brush_overlay,
1342     VIEW3D_PT_tools_brush_texture,
1343     VIEW3D_PT_tools_mask_texture,
1344     VIEW3D_PT_tools_brush_stroke,
1345     VIEW3D_PT_tools_brush_curve,
1346     VIEW3D_PT_sculpt_dyntopo,
1347     VIEW3D_PT_sculpt_options,
1348     VIEW3D_PT_sculpt_symmetry,
1349     VIEW3D_PT_tools_brush_appearance,
1350     VIEW3D_PT_tools_weightpaint_symmetry,
1351     VIEW3D_PT_tools_weightpaint_options,
1352     VIEW3D_PT_tools_vertexpaint,
1353     VIEW3D_PT_tools_vertexpaint_symmetry,
1354     VIEW3D_PT_tools_imagepaint_external,
1355     VIEW3D_PT_tools_imagepaint_symmetry,
1356     VIEW3D_PT_tools_projectpaint,
1357     VIEW3D_MT_tools_projectpaint_stencil,
1358     VIEW3D_PT_tools_particlemode,
1359     VIEW3D_PT_tools_grease_pencil_draw,
1360     VIEW3D_PT_tools_grease_pencil_edit,
1361     VIEW3D_PT_tools_grease_pencil_interpolate,
1362     VIEW3D_PT_tools_grease_pencil_sculpt,
1363     VIEW3D_PT_tools_grease_pencil_brush,
1364     VIEW3D_PT_tools_grease_pencil_brushcurves,
1365 )
1366
1367 if __name__ == "__main__":  # only for live edit.
1368     from bpy.utils import register_class
1369     for cls in classes:
1370         register_class(cls)