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