Tool System: show weight for the gradient tool
[blender.git] / release / scripts / startup / bl_ui / space_toolsystem_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
21 # For now group all tools together
22 # we may want to move these into per space-type files.
23 #
24 # For now keep this in a single file since it's an area that may change,
25 # so avoid making changes all over the place.
26
27 import bpy
28 from bpy.types import Panel
29
30 from .space_toolsystem_common import (
31     ToolSelectPanelHelper,
32     ToolDef,
33 )
34
35
36 def generate_from_brushes_ex(
37         context, *,
38         icon_prefix,
39         brush_test_attr,
40         brush_category_attr,
41         brush_category_layout,
42 ):
43     # Categories
44     brush_categories = {}
45     if context.mode != 'GPENCIL_PAINT':
46         for brush in context.blend_data.brushes:
47             if getattr(brush, brush_test_attr) and brush.gpencil_settings is None:
48                 category = getattr(brush, brush_category_attr)
49                 name = brush.name
50                 brush_categories.setdefault(category, []).append(
51                     ToolDef.from_dict(
52                         dict(
53                             text=name,
54                             icon=icon_prefix + category.lower(),
55                             data_block=name,
56                         )
57                     )
58                 )
59     else:
60         def draw_settings(context, layout, tool):
61             _defs_gpencil_paint.draw_settings_common(context, layout, tool)
62
63         for brush_type in brush_category_layout:
64             for brush in context.blend_data.brushes:
65                 if getattr(brush, brush_test_attr) and brush.gpencil_settings.gp_icon == brush_type[0]:
66                     category = brush_type[0]
67                     name = brush.name
68                     text = name
69
70                     # XXX, disabled since changing the brush needs to sync back to the tool.
71                     """
72                     # rename default brushes for tool bar
73                     if name.startswith("Draw "):
74                         text = name.replace("Draw ", "")
75                     elif name.startswith("Eraser "):
76                         text = name.replace("Eraser ", "")
77                     elif name.startswith("Fill "):
78                         text = name.replace(" Area", "")
79                     else:
80                         text = name
81                     """
82                     # Define icon.
83                     icon_name = {
84                         'PENCIL': 'draw_pencil',
85                         'PEN': 'draw_pen',
86                         'INK': 'draw_ink',
87                         'INKNOISE': 'draw_noise',
88                         'BLOCK': 'draw_block',
89                         'MARKER': 'draw_marker',
90                         'FILL': 'draw_fill',
91                         'SOFT': 'draw.eraser_soft',
92                         'HARD': 'draw.eraser_hard',
93                         'STROKE': 'draw.eraser_stroke',
94                     }[category]
95                     brush_categories.setdefault(category, []).append(
96                         ToolDef.from_dict(
97                             dict(
98                                 text=text,
99                                 icon=icon_prefix + icon_name,
100                                 data_block=name,
101                                 widget=None,
102                                 operator="gpencil.draw",
103                                 draw_settings=draw_settings,
104                             )
105                         )
106                     )
107
108     def tools_from_brush_group(groups):
109         assert(type(groups) is tuple)
110         if len(groups) == 1:
111             tool_defs = tuple(brush_categories.pop(groups[0], ()))
112         else:
113             tool_defs = tuple(item for g in groups for item in brush_categories.pop(g, ()))
114
115         if len(tool_defs) > 1:
116             return (tool_defs,)
117         else:
118             return tool_defs
119
120     # Each item below is a single toolbar entry:
121     # Grouped for multiple or none if no brushes are found.
122     tool_defs = tuple(
123         tool_def
124         for category in brush_category_layout
125         for tool_def in tools_from_brush_group(category)
126     )
127     # Ensure we use all types.
128     if brush_categories:
129         print(brush_categories)
130     assert(len(brush_categories) == 0)
131     return tool_defs
132
133
134 def generate_from_enum_ex(
135         context, *,
136         icon_prefix,
137         data,
138         attr,
139 ):
140     tool_defs = []
141     for enum in data.rna_type.properties[attr].enum_items_static:
142         name = enum.name
143         identifier = enum.identifier
144         tool_defs.append(
145             ToolDef.from_dict(
146                 dict(
147                     text=name,
148                     icon=icon_prefix + identifier.lower(),
149                     data_block=identifier,
150                 )
151             )
152         )
153     return tuple(tool_defs)
154
155
156 class _defs_view3d_generic:
157     @ToolDef.from_fn
158     def cursor():
159         def draw_settings(context, layout, tool):
160             props = tool.operator_properties("view3d.cursor3d")
161             layout.prop(props, "use_depth")
162             layout.prop(props, "orientation")
163
164         return dict(
165             text="Cursor",
166             description=(
167                 "Set the 3D cursor location, drag to transform"
168             ),
169             icon="ops.generic.cursor",
170             keymap=(
171                 ("view3d.cursor3d", dict(), dict(type='ACTIONMOUSE', value='PRESS')),
172                 ("transform.translate",
173                  dict(release_confirm=True, cursor_transform=True),
174                  dict(type='EVT_TWEAK_A', value='ANY'),
175                  ),
176             ),
177             draw_settings=draw_settings,
178         )
179
180     @ToolDef.from_fn
181     def cursor_click():
182         return dict(
183             text="None",
184             icon="ops.generic.cursor",
185             keymap=(
186                 # This is a dummy keymap entry, until particle system is properly working with toolsystem.
187                 ("view3d.cursor3d", dict(), dict(type='ACTIONMOUSE', value='CLICK', ctrl=True, alt=True, shift=True)),
188             ),
189         )
190
191     @ToolDef.from_fn
192     def ruler():
193         return dict(
194             text="Measure",
195             icon="ops.view3d.ruler",
196             widget="VIEW3D_GGT_ruler",
197             keymap=(
198                 ("view3d.ruler_add", dict(), dict(type='EVT_TWEAK_A', value='ANY')),
199             ),
200         )
201
202
203 def _defs_annotate_factory():
204
205     class _defs_annotate:
206         @staticmethod
207         def draw_settings_common(context, layout, tool):
208             ts = context.tool_settings
209
210             space_type = tool.space_type
211             if space_type == 'VIEW_3D':
212                 layout.separator()
213
214                 row = layout.row(align=True)
215                 row.prop(ts, "annotation_stroke_placement_view3d", text="Placement")
216                 if ts.gpencil_stroke_placement_view3d == 'CURSOR':
217                     row.prop(ts.gpencil_sculpt, "lockaxis")
218                 elif ts.gpencil_stroke_placement_view3d in {'SURFACE', 'STROKE'}:
219                     row.prop(ts, "use_gpencil_stroke_endpoints")
220
221         @ToolDef.from_fn
222         def scribble():
223             def draw_settings(context, layout, tool):
224                 _defs_annotate.draw_settings_common(context, layout, tool)
225
226             return dict(
227                 text="Annotate",
228                 icon="ops.gpencil.draw",
229                 cursor='PAINT_BRUSH',
230                 keymap=(
231                     ("gpencil.annotate",
232                      dict(mode='DRAW', wait_for_input=False),
233                      dict(type='EVT_TWEAK_A', value='ANY')),
234                 ),
235                 draw_settings=draw_settings,
236             )
237
238         @ToolDef.from_fn
239         def line():
240             def draw_settings(context, layout, tool):
241                 _defs_annotate.draw_settings_common(context, layout, tool)
242
243             return dict(
244                 text="Annotate Line",
245                 icon="ops.gpencil.draw.line",
246                 cursor='CROSSHAIR',
247                 keymap=(
248                     ("gpencil.annotate",
249                      dict(mode='DRAW_STRAIGHT', wait_for_input=False),
250                      dict(type='EVT_TWEAK_A', value='ANY')),
251                 ),
252                 draw_settings=draw_settings,
253             )
254
255         @ToolDef.from_fn
256         def poly():
257             def draw_settings(context, layout, tool):
258                 _defs_annotate.draw_settings_common(context, layout, tool)
259
260             return dict(
261                 text="Annotate Polygon",
262                 icon="ops.gpencil.draw.poly",
263                 cursor='CROSSHAIR',
264                 keymap=(
265                     ("gpencil.annotate",
266                      dict(mode='DRAW_POLY', wait_for_input=False),
267                      dict(type='ACTIONMOUSE', value='PRESS')),
268                 ),
269                 draw_settings=draw_settings,
270             )
271
272         @ToolDef.from_fn
273         def eraser():
274             def draw_settings(context, layout, tool):
275                 # TODO: Move this setting to toolsettings
276                 user_prefs = context.user_preferences
277                 layout.prop(user_prefs.edit, "grease_pencil_eraser_radius", text="Radius")
278
279             return dict(
280                 text="Annotate Eraser",
281                 icon="ops.gpencil.draw.eraser",
282                 cursor='CROSSHAIR',  # XXX: Always show brush circle when enabled
283                 keymap=(
284                     ("gpencil.annotate",
285                      dict(mode='ERASER', wait_for_input=False),
286                      dict(type='ACTIONMOUSE', value='PRESS')),
287                 ),
288                 draw_settings=draw_settings,
289             )
290     return _defs_annotate
291
292
293 # Needed so annotation gets a keymap per space type.
294 _defs_annotate_image = _defs_annotate_factory()
295 _defs_annotate_view3d = _defs_annotate_factory()
296
297
298 class _defs_transform:
299
300     @ToolDef.from_fn
301     def translate():
302         def draw_settings(context, layout, tool):
303             tool_settings = context.tool_settings
304             layout.prop(tool_settings, "use_gizmo_apron")
305
306         return dict(
307             text="Grab",
308             # cursor='SCROLL_XY',
309             icon="ops.transform.translate",
310             widget="TRANSFORM_GGT_gizmo",
311             operator="transform.translate",
312             # TODO, implement as optional fallback gizmo
313             # keymap=(
314             #     ("transform.translate", dict(release_confirm=True), dict(type='EVT_TWEAK_A', value='ANY')),
315             # ),
316             draw_settings=draw_settings,
317         )
318
319     @ToolDef.from_fn
320     def rotate():
321         def draw_settings(context, layout, tool):
322             tool_settings = context.tool_settings
323             layout.prop(tool_settings, "use_gizmo_apron")
324
325         return dict(
326             text="Rotate",
327             # cursor='SCROLL_XY',
328             icon="ops.transform.rotate",
329             widget="TRANSFORM_GGT_gizmo",
330             operator="transform.rotate",
331             # TODO, implement as optional fallback gizmo
332             # keymap=(
333             #     ("transform.rotate", dict(release_confirm=True), dict(type='EVT_TWEAK_A', value='ANY')),
334             # ),
335             draw_settings=draw_settings,
336         )
337
338     @ToolDef.from_fn
339     def scale():
340         def draw_settings(context, layout, tool):
341             tool_settings = context.tool_settings
342             layout.prop(tool_settings, "use_gizmo_apron")
343
344         return dict(
345             text="Scale",
346             # cursor='SCROLL_XY',
347             icon="ops.transform.resize",
348             widget="TRANSFORM_GGT_gizmo",
349             operator="transform.resize",
350             # TODO, implement as optional fallback gizmo
351             # keymap=(
352             #     ("transform.resize", dict(release_confirm=True), dict(type='EVT_TWEAK_A', value='ANY')),
353             # ),
354             draw_settings=draw_settings,
355         )
356
357     @ToolDef.from_fn
358     def scale_cage():
359         return dict(
360             text="Scale Cage",
361             icon="ops.transform.resize.cage",
362             widget="VIEW3D_GGT_xform_cage",
363             operator="transform.resize",
364         )
365
366     @ToolDef.from_fn
367     def transform():
368         def draw_settings(context, layout, tool):
369             tool_settings = context.tool_settings
370             layout.prop(tool_settings, "use_gizmo_apron")
371             layout.prop(tool_settings, "use_gizmo_mode")
372
373         return dict(
374             text="Transform",
375             description=(
376                 "Supports any combination of grab, rotate & scale at once"
377             ),
378             icon="ops.transform.transform",
379             widget="TRANSFORM_GGT_gizmo",
380             # No keymap default action, only for gizmo!
381             draw_settings=draw_settings,
382         )
383
384
385 class _defs_view3d_select:
386
387     @ToolDef.from_fn
388     def border():
389         def draw_settings(context, layout, tool):
390             props = tool.operator_properties("view3d.select_border")
391             layout.prop(props, "mode", expand=True)
392         return dict(
393             text="Select Border",
394             icon="ops.generic.select_border",
395             widget=None,
396             keymap=(
397                 ("view3d.select_border",
398                  dict(mode='ADD'),
399                  dict(type='EVT_TWEAK_A', value='ANY')),
400                 ("view3d.select_border",
401                  dict(mode='SUB'),
402                  dict(type='EVT_TWEAK_A', value='ANY', ctrl=True)),
403             ),
404             draw_settings=draw_settings,
405         )
406
407     @ToolDef.from_fn
408     def circle():
409         def draw_settings(context, layout, tool):
410             props = tool.operator_properties("view3d.select_circle")
411             layout.prop(props, "radius")
412         return dict(
413             text="Select Circle",
414             icon="ops.generic.select_circle",
415             widget=None,
416             keymap=(
417                 ("view3d.select_circle",
418                  dict(deselect=False),
419                  dict(type='ACTIONMOUSE', value='PRESS')),
420                 ("view3d.select_circle",
421                  dict(deselect=True),
422                  dict(type='ACTIONMOUSE', value='PRESS', ctrl=True)),
423             ),
424             draw_settings=draw_settings,
425         )
426
427     @ToolDef.from_fn
428     def lasso():
429         def draw_settings(context, layout, tool):
430             props = tool.operator_properties("view3d.select_lasso")
431             layout.prop(props, "mode", expand=True)
432         return dict(
433             text="Select Lasso",
434             icon="ops.generic.select_lasso",
435             widget=None,
436             keymap=(
437                 ("view3d.select_lasso",
438                  dict(mode='ADD'),
439                  dict(type='EVT_TWEAK_A', value='ANY')),
440                 ("view3d.select_lasso",
441                  dict(mode='SUB'),
442                  dict(type='EVT_TWEAK_A', value='ANY', ctrl=True)),
443             ),
444             draw_settings=draw_settings,
445         )
446 # -----------------------------------------------------------------------------
447 # Object Modes (named based on context.mode)
448
449
450 class _defs_edit_armature:
451
452     @ToolDef.from_fn
453     def roll():
454         return dict(
455             text="Roll",
456             icon="ops.armature.bone.roll",
457             widget=None,
458             keymap=(
459                 ("transform.transform",
460                  dict(release_confirm=True, mode='BONE_ROLL'),
461                  dict(type='EVT_TWEAK_A', value='ANY'),),
462             ),
463         )
464
465     @ToolDef.from_fn
466     def bone_envelope():
467         return dict(
468             text="Bone Envelope",
469             icon="ops.transform.bone_envelope",
470             widget=None,
471             keymap=(
472                 ("transform.transform",
473                  dict(release_confirm=True, mode='BONE_ENVELOPE'),
474                  dict(type='ACTIONMOUSE', value='PRESS')),
475             ),
476         )
477
478     @ToolDef.from_fn
479     def bone_size():
480         return dict(
481             text="Bone Size",
482             icon="ops.transform.bone_size",
483             widget=None,
484             keymap=(
485                 ("transform.transform",
486                  dict(release_confirm=True, mode='BONE_SIZE'),
487                  dict(type='ACTIONMOUSE', value='PRESS')),
488             ),
489         )
490
491     @ToolDef.from_fn
492     def extrude():
493         return dict(
494             text="Extrude",
495             icon="ops.armature.extrude_move",
496             widget=None,
497             keymap=(
498                 ("armature.extrude_move",
499                  dict(TRANSFORM_OT_translate=dict(release_confirm=True)),
500                  dict(type='EVT_TWEAK_A', value='ANY')),
501             ),
502         )
503
504     @ToolDef.from_fn
505     def extrude_cursor():
506         return dict(
507             text="Extrude to Cursor",
508             icon="ops.armature.extrude_cursor",
509             widget=None,
510             keymap=(
511                 ("armature.click_extrude", dict(), dict(type='ACTIONMOUSE', value='PRESS')),
512             ),
513         )
514
515
516 class _defs_edit_mesh:
517
518     @ToolDef.from_fn
519     def cube_add():
520         return dict(
521             text="Add Cube",
522             icon="ops.mesh.primitive_cube_add_gizmo",
523             widget=None,
524             keymap=(
525                 ("view3d.cursor3d", dict(), dict(type='ACTIONMOUSE', value='CLICK')),
526                 ("mesh.primitive_cube_add_gizmo", dict(), dict(type='EVT_TWEAK_A', value='ANY')),
527             ),
528         )
529
530     @ToolDef.from_fn
531     def rip_region():
532         def draw_settings(context, layout, tool):
533             props = tool.operator_properties("mesh.rip_move")
534             props_macro = props.MESH_OT_rip
535             layout.prop(props_macro, "use_fill")
536
537         return dict(
538             text="Rip Region",
539             icon="ops.mesh.rip",
540             widget=None,
541             keymap=(
542                 ("mesh.rip_move",
543                  dict(TRANSFORM_OT_translate=dict(release_confirm=True)),
544                  dict(type='ACTIONMOUSE', value='PRESS')),
545             ),
546             draw_settings=draw_settings,
547         )
548
549     @ToolDef.from_fn
550     def rip_edge():
551         return dict(
552             text="Rip Edge",
553             icon="ops.mesh.rip_edge",
554             widget=None,
555             keymap=(
556                 ("mesh.rip_edge_move",
557                  dict(TRANSFORM_OT_translate=dict(release_confirm=True)),
558                  dict(type='ACTIONMOUSE', value='PRESS')),
559             ),
560         )
561
562     @ToolDef.from_fn
563     def poly_build():
564         return dict(
565             text="Poly Build",
566             icon="ops.mesh.polybuild_hover",
567             widget=None,
568             keymap=(
569                 ("mesh.polybuild_face_at_cursor_move",
570                  dict(TRANSFORM_OT_translate=dict(release_confirm=True)),
571                  dict(type='ACTIONMOUSE', value='PRESS')),
572                 ("mesh.polybuild_split_at_cursor_move",
573                  dict(TRANSFORM_OT_translate=dict(release_confirm=True)),
574                  dict(type='ACTIONMOUSE', value='PRESS', ctrl=True)),
575                 ("mesh.polybuild_dissolve_at_cursor", dict(), dict(type='ACTIONMOUSE', value='CLICK', alt=True)),
576                 ("mesh.polybuild_hover", dict(use_boundary=False), dict(type='MOUSEMOVE', value='ANY', alt=True)),
577                 ("mesh.polybuild_hover", dict(use_boundary=True), dict(type='MOUSEMOVE', value='ANY', any=True)),
578             ),
579         )
580
581     @ToolDef.from_fn
582     def edge_slide():
583         def draw_settings(context, layout, tool):
584             props = tool.operator_properties("transform.edge_slide")
585             layout.prop(props, "correct_uv")
586
587         return dict(
588             text="Edge Slide",
589             icon="ops.transform.edge_slide",
590             widget=None,
591             keymap=(
592                 ("transform.edge_slide", dict(release_confirm=True),
593                  dict(type='ACTIONMOUSE', value='PRESS')
594                  ),
595             ),
596             draw_settings=draw_settings,
597         )
598
599     @ToolDef.from_fn
600     def vert_slide():
601         def draw_settings(context, layout, tool):
602             props = tool.operator_properties("transform.vert_slide")
603             layout.prop(props, "correct_uv")
604
605         return dict(
606             text="Vertex Slide",
607             icon="ops.transform.vert_slide",
608             widget=None,
609             keymap=(
610                 ("transform.vert_slide", dict(release_confirm=True),
611                  dict(type='ACTIONMOUSE', value='PRESS')),
612             ),
613             draw_settings=draw_settings,
614         )
615
616     @ToolDef.from_fn
617     def spin():
618         return dict(
619             text="Spin",
620             icon="ops.mesh.spin",
621             widget=None,
622             keymap=(
623                 ("mesh.spin", dict(),
624                  dict(type='ACTIONMOUSE', value='PRESS')),
625             ),
626         )
627
628     @ToolDef.from_fn
629     def spin_duplicate():
630         return dict(
631             text="Spin (Duplicate)",
632             icon="ops.mesh.spin.duplicate",
633             widget=None,
634             keymap=(
635                 ("mesh.spin", dict(dupli=True),
636                  dict(type='ACTIONMOUSE', value='PRESS')),
637             ),
638         )
639
640     @ToolDef.from_fn
641     def inset():
642         def draw_settings(context, layout, tool):
643             props = tool.operator_properties("mesh.inset")
644             layout.prop(props, "use_outset")
645             layout.prop(props, "use_individual")
646             layout.prop(props, "use_even_offset")
647             layout.prop(props, "use_relative_offset")
648
649         return dict(
650             text="Inset Faces",
651             icon="ops.mesh.inset",
652             widget=None,
653             keymap=(
654                 ("mesh.inset", dict(release_confirm=True),
655                  dict(type='ACTIONMOUSE', value='PRESS')),
656             ),
657             draw_settings=draw_settings,
658         )
659
660     @ToolDef.from_fn
661     def bevel():
662         def draw_settings(context, layout, tool):
663             props = tool.operator_properties("mesh.bevel")
664             layout.prop(props, "offset_type")
665             layout.prop(props, "segments")
666             layout.prop(props, "profile", slider=True)
667             layout.prop(props, "vertex_only")
668
669         return dict(
670             text="Bevel",
671             icon="ops.mesh.bevel",
672             widget=None,
673             keymap=(
674                 ("mesh.bevel", dict(release_confirm=True),
675                  dict(type='ACTIONMOUSE', value='PRESS')),
676             ),
677             draw_settings=draw_settings,
678         )
679
680     @ToolDef.from_fn
681     def extrude():
682         return dict(
683             text="Extrude Region",
684             icon="ops.mesh.extrude_region_move",
685             widget="MESH_GGT_extrude",
686             operator="view3d.edit_mesh_extrude_move_normal",
687             keymap=(
688                 ("mesh.extrude_context_move",
689                  dict(TRANSFORM_OT_translate=dict(release_confirm=True)),
690                  dict(type='EVT_TWEAK_A', value='ANY')),
691             ),
692         )
693
694     @ToolDef.from_fn
695     def extrude_normals():
696         def draw_settings(context, layout, tool):
697             props = tool.operator_properties("mesh.extrude_region_shrink_fatten")
698             props_macro = props.TRANSFORM_OT_shrink_fatten
699             layout.prop(props_macro, "use_even_offset")
700         return dict(
701             text="Extrude Along Normals",
702             icon="ops.mesh.extrude_region_shrink_fatten",
703             widget=None,
704             keymap=(
705                 ("mesh.extrude_region_shrink_fatten",
706                  dict(TRANSFORM_OT_shrink_fatten=dict(release_confirm=True)),
707                  dict(type='EVT_TWEAK_A', value='ANY')),
708             ),
709             draw_settings=draw_settings,
710         )
711
712     @ToolDef.from_fn
713     def extrude_individual():
714         return dict(
715             text="Extrude Individual",
716             icon="ops.mesh.extrude_faces_move",
717             widget=None,
718             keymap=(
719                 ("mesh.extrude_faces_move", dict(TRANSFORM_OT_shrink_fatten=dict(release_confirm=True)),
720                  dict(type='EVT_TWEAK_A', value='ANY')),
721             ),
722         )
723
724     @ToolDef.from_fn
725     def extrude_cursor():
726         return dict(
727             text="Extrude to Cursor",
728             icon="ops.mesh.dupli_extrude_cursor",
729             widget=None,
730             keymap=(
731                 ("mesh.dupli_extrude_cursor", dict(), dict(type='ACTIONMOUSE', value='PRESS')),
732             ),
733         )
734
735     @ToolDef.from_fn
736     def loopcut_slide():
737
738         def draw_settings(context, layout, tool):
739             props = tool.operator_properties("mesh.loopcut_slide")
740             props_macro = props.MESH_OT_loopcut
741             layout.prop(props_macro, "number_cuts")
742             props_macro = props.TRANSFORM_OT_edge_slide
743             layout.prop(props_macro, "correct_uv")
744
745         return dict(
746             text="Loop Cut",
747             icon="ops.mesh.loopcut_slide",
748             widget="VIEW3D_GGT_mesh_preselect_edgering",
749             keymap=(
750                 ("mesh.loopcut_slide",
751                  dict(TRANSFORM_OT_edge_slide=dict(release_confirm=True)),
752                  dict(type='ACTIONMOUSE', value='PRESS')),
753             ),
754             draw_settings=draw_settings,
755         )
756
757     @ToolDef.from_fn
758     def offset_edge_loops_slide():
759         return dict(
760             text="Offset Edge Loop Cut",
761             icon="ops.mesh.offset_edge_loops_slide",
762             widget=None,
763             keymap=(
764                 ("mesh.offset_edge_loops_slide", dict(), dict(type='ACTIONMOUSE', value='PRESS')),
765             ),
766         )
767
768     @ToolDef.from_fn
769     def vertex_smooth():
770         return dict(
771             text="Smooth",
772             icon="ops.mesh.vertices_smooth",
773             widget=None,
774             keymap=(
775                 ("mesh.vertices_smooth", dict(),
776                  dict(type='ACTIONMOUSE', value='PRESS')),
777             ),
778         )
779
780     @ToolDef.from_fn
781     def vertex_randomize():
782         return dict(
783             text="Randomize",
784             icon="ops.transform.vertex_random",
785             widget=None,
786             keymap=(
787                 ("transform.vertex_random", dict(),
788                  dict(type='ACTIONMOUSE', value='PRESS')),
789             ),
790         )
791
792     @ToolDef.from_fn
793     def shear():
794         return dict(
795             text="Shear",
796             icon="ops.transform.shear",
797             widget=None,
798             keymap=(
799                 ("transform.shear", dict(release_confirm=True),
800                  dict(type='ACTIONMOUSE', value='PRESS')),
801             ),
802         )
803
804     @ToolDef.from_fn
805     def tosphere():
806         return dict(
807             text="To Sphere",
808             icon="ops.transform.tosphere",
809             widget=None,
810             keymap=(
811                 ("transform.tosphere", dict(release_confirm=True),
812                  dict(type='ACTIONMOUSE', value='PRESS')),
813             ),
814         )
815
816     @ToolDef.from_fn
817     def shrink_fatten():
818         def draw_settings(context, layout, tool):
819             props = tool.operator_properties("transform.shrink_fatten")
820             layout.prop(props, "use_even_offset")
821
822         return dict(
823             text="Shrink/Fatten",
824             icon="ops.transform.shrink_fatten",
825             widget=None,
826             keymap=(
827                 ("transform.shrink_fatten", dict(release_confirm=True),
828                  dict(type='ACTIONMOUSE', value='PRESS')),
829             ),
830             draw_settings=draw_settings,
831         )
832
833     @ToolDef.from_fn
834     def push_pull():
835         return dict(
836             text="Push/Pull",
837             icon="ops.transform.push_pull",
838             widget=None,
839             keymap=(
840                 ("transform.push_pull", dict(release_confirm=True),
841                  dict(type='ACTIONMOUSE', value='PRESS')),
842             ),
843         )
844
845     @ToolDef.from_fn
846     def knife():
847         def draw_settings(context, layout, tool):
848             props = tool.operator_properties("mesh.knife_tool")
849             layout.prop(props, "use_occlude_geometry")
850             layout.prop(props, "only_selected")
851
852         return dict(
853             text="Knife",
854             icon="ops.mesh.knife_tool",
855             widget=None,
856             keymap=(
857                 ("mesh.knife_tool",
858                  dict(wait_for_input=False),
859                  dict(type='ACTIONMOUSE', value='PRESS')),
860             ),
861             draw_settings=draw_settings,
862         )
863
864     @ToolDef.from_fn
865     def bisect():
866         return dict(
867             text="Bisect",
868             icon="ops.mesh.bisect",
869             widget=None,
870             keymap=(
871                 ("mesh.bisect",
872                  dict(),
873                  dict(type='EVT_TWEAK_A', value='ANY')),
874             ),
875         )
876
877
878 class _defs_edit_curve:
879
880     @ToolDef.from_fn
881     def draw():
882         def draw_settings(context, layout, tool):
883             # Tool settings initialize operator options.
884             tool_settings = context.tool_settings
885             cps = tool_settings.curve_paint_settings
886
887             col = layout.row()
888
889             col.prop(cps, "curve_type")
890
891             if cps.curve_type == 'BEZIER':
892                 col.prop(cps, "error_threshold")
893                 col.prop(cps, "fit_method")
894                 col.prop(cps, "use_corners_detect")
895
896                 col = layout.row()
897                 col.active = cps.use_corners_detect
898                 col.prop(cps, "corner_angle")
899
900         return dict(
901             text="Draw",
902             cursor='PAINT_BRUSH',
903             icon=None,
904             widget=None,
905             keymap=(
906                 ("curve.draw", dict(wait_for_input=False), dict(type='ACTIONMOUSE', value='PRESS')),
907             ),
908             draw_settings=draw_settings,
909         )
910
911     @ToolDef.from_fn
912     def extrude():
913         return dict(
914             text="Extrude",
915             icon=None,
916             widget=None,
917             keymap=(
918                 ("curve.extrude_move",
919                  dict(TRANSFORM_OT_translate=dict(release_confirm=True)),
920                  dict(type='EVT_TWEAK_A', value='ANY')),
921             ),
922         )
923
924     @ToolDef.from_fn
925     def extrude_cursor():
926         return dict(
927             text="Extrude Cursor",
928             icon=None,
929             widget=None,
930             keymap=(
931                 ("curve.vertex_add", dict(), dict(type='ACTIONMOUSE', value='PRESS')),
932             ),
933         )
934
935
936 class _defs_pose:
937
938     @ToolDef.from_fn
939     def breakdown():
940         return dict(
941             text="Breakdowner",
942             icon="ops.pose.breakdowner",
943             widget=None,
944             keymap=(
945                 ("pose.breakdown", dict(), dict(type='ACTIONMOUSE', value='PRESS')),
946             ),
947         )
948
949     @ToolDef.from_fn
950     def push():
951         return dict(
952             text="Push",
953             icon="ops.pose.push",
954             widget=None,
955             keymap=(
956                 ("pose.push", dict(), dict(type='ACTIONMOUSE', value='PRESS')),
957             ),
958         )
959
960     @ToolDef.from_fn
961     def relax():
962         return dict(
963             text="Relax",
964             icon="ops.pose.relax",
965             widget=None,
966             keymap=(
967                 ("pose.relax", dict(), dict(type='ACTIONMOUSE', value='PRESS')),
968             ),
969         )
970
971
972 class _defs_particle:
973
974     @staticmethod
975     def generate_from_brushes(context):
976         return generate_from_enum_ex(
977             context,
978             icon_prefix="brush.particle.",
979             data=context.tool_settings.particle_edit,
980             attr="tool",
981         )
982
983
984 class _defs_sculpt:
985
986     @staticmethod
987     def generate_from_brushes(context):
988         return generate_from_brushes_ex(
989             context,
990             icon_prefix="brush.sculpt.",
991             brush_test_attr="use_paint_sculpt",
992             brush_category_attr="sculpt_tool",
993             brush_category_layout=(
994                 ('DRAW',),
995                 ('GRAB', 'THUMB'),
996                 ('SNAKE_HOOK',),
997                 ('BLOB', 'INFLATE'),
998                 ('SMOOTH', 'SCRAPE', 'FLATTEN'),
999                 ('CREASE', 'PINCH'),
1000                 ('CLAY', 'CLAY_STRIPS'),
1001                 ('LAYER',),
1002                 ('NUDGE', 'ROTATE'),
1003                 ('FILL',),
1004                 ('SIMPLIFY',),
1005                 ('MASK',),
1006             )
1007         )
1008
1009     @ToolDef.from_fn
1010     def hide_border():
1011         return dict(
1012             text="Border Hide",
1013             icon="ops.sculpt.border_hide",
1014             widget=None,
1015             keymap=(
1016                 ("paint.hide_show", dict(action='HIDE'), dict(type='EVT_TWEAK_A', value='ANY')),
1017                 ("paint.hide_show", dict(action='SHOW'), dict(type='EVT_TWEAK_A', value='ANY', ctrl=True)),
1018                 ("paint.hide_show", dict(action='SHOW', area='ALL'), dict(type='SELECTMOUSE', value='PRESS')),
1019             ),
1020         )
1021
1022     @ToolDef.from_fn
1023     def mask_border():
1024         return dict(
1025             text="Border Mask",
1026             icon="ops.sculpt.border_mask",
1027             widget=None,
1028             keymap=(
1029                 ("view3d.select_border", dict(mode='ADD'), dict(type='EVT_TWEAK_A', value='ANY')),
1030                 ("view3d.select_border", dict(mode='SUB'), dict(type='EVT_TWEAK_A', value='ANY', ctrl=True)),
1031             ),
1032         )
1033
1034
1035 class _defs_vertex_paint:
1036
1037     @staticmethod
1038     def poll_select_mask(context):
1039         mesh = context.object.data
1040         return mesh.use_paint_mask
1041
1042     @staticmethod
1043     def generate_from_brushes(context):
1044         return generate_from_brushes_ex(
1045             context,
1046             icon_prefix="brush.paint_vertex.",
1047             brush_test_attr="use_paint_vertex",
1048             brush_category_attr="vertex_tool",
1049             brush_category_layout=(
1050                 ('MIX',),
1051                 ('BLUR', 'AVERAGE'),
1052                 ('SMEAR',),
1053                 (
1054                     'ADD', 'SUB', 'MUL', 'LIGHTEN', 'DARKEN',
1055                     'COLORDODGE', 'DIFFERENCE', 'SCREEN', 'HARDLIGHT',
1056                     'OVERLAY', 'SOFTLIGHT', 'EXCLUSION', 'LUMINOCITY',
1057                     'SATURATION', 'HUE', 'ERASE_ALPHA', 'ADD_ALPHA',
1058                 ),
1059             )
1060         )
1061
1062
1063 class _defs_texture_paint:
1064
1065     @staticmethod
1066     def generate_from_brushes(context):
1067         return generate_from_brushes_ex(
1068             context,
1069             icon_prefix="brush.paint_texture.",
1070             brush_test_attr="use_paint_image",
1071             brush_category_attr="image_tool",
1072             brush_category_layout=(
1073                 ('DRAW',),
1074                 ('SOFTEN',),
1075                 ('SMEAR',),
1076                 ('CLONE',),
1077                 ('FILL',),
1078                 ('MASK',),
1079             )
1080         )
1081
1082
1083 class _defs_weight_paint:
1084
1085     @staticmethod
1086     def poll_select_mask(context):
1087         mesh = context.object.data
1088         return (mesh.use_paint_mask or mesh.use_paint_mask_vertex)
1089
1090     @staticmethod
1091     def generate_from_brushes(context):
1092         return generate_from_brushes_ex(
1093             context,
1094             icon_prefix="brush.paint_weight.",
1095             brush_test_attr="use_paint_weight",
1096             brush_category_attr="vertex_tool",
1097             brush_category_layout=(
1098                 ('MIX',),
1099                 ('BLUR', 'AVERAGE'),
1100                 ('SMEAR',),
1101                 (
1102                     'ADD', 'SUB', 'MUL', 'LIGHTEN', 'DARKEN',
1103                     'COLORDODGE', 'DIFFERENCE', 'SCREEN', 'HARDLIGHT',
1104                     'OVERLAY', 'SOFTLIGHT', 'EXCLUSION', 'LUMINOCITY',
1105                     'SATURATION', 'HUE',
1106                 ),
1107             )
1108         )
1109
1110     @ToolDef.from_fn
1111     def sample_weight():
1112         return dict(
1113             text="Sample Weight",
1114             icon="ops.paint.weight_sample",
1115             widget=None,
1116             keymap=(
1117                 ("paint.weight_sample", dict(), dict(type='ACTIONMOUSE', value='PRESS')),
1118             ),
1119         )
1120
1121     @ToolDef.from_fn
1122     def sample_weight_group():
1123         return dict(
1124             text="Sample Vertex Group",
1125             icon="ops.paint.weight_sample_group",
1126             widget=None,
1127             keymap=(
1128                 ("paint.weight_sample_group", dict(), dict(type='ACTIONMOUSE', value='PRESS')),
1129             ),
1130         )
1131
1132     @ToolDef.from_fn
1133     def gradient():
1134         def draw_settings(context, layout, tool):
1135             props = tool.operator_properties("paint.weight_gradient")
1136             layout.prop(props, "type")
1137             brush = context.tool_settings.weight_paint.brush
1138             if brush is not None:
1139                 from .properties_paint_common import UnifiedPaintPanel
1140                 UnifiedPaintPanel.prop_unified_weight(layout, context, brush, "weight", slider=True, text="Weight")
1141
1142         return dict(
1143             text="Gradient",
1144             icon="ops.paint.weight_gradient",
1145             widget=None,
1146             keymap=(
1147                 ("paint.weight_gradient", dict(), dict(type='EVT_TWEAK_A', value='ANY')),
1148             ),
1149             draw_settings=draw_settings,
1150         )
1151
1152
1153 class _defs_uv_select:
1154
1155     @ToolDef.from_fn
1156     def border():
1157         return dict(
1158             text="Select Border",
1159             icon="ops.generic.select_border",
1160             widget=None,
1161             keymap=(
1162                 ("uv.select_border",
1163                  dict(deselect=False),
1164                  dict(type='EVT_TWEAK_A', value='ANY')),
1165                 # ("uv.select_border",
1166                 #  dict(deselect=True),
1167                 #  dict(type='EVT_TWEAK_A', value='ANY', ctrl=True)),
1168             ),
1169         )
1170
1171     @ToolDef.from_fn
1172     def circle():
1173         return dict(
1174             text="Select Circle",
1175             icon="ops.generic.select_circle",
1176             widget=None,
1177             keymap=(
1178                 ("uv.select_circle",
1179                  dict(),  # dict(deselect=False),
1180                  dict(type='ACTIONMOUSE', value='PRESS')),
1181                 # ("uv.select_circle",
1182                 #  dict(deselect=True),
1183                 #  dict(type='ACTIONMOUSE', value='PRESS', ctrl=True)),
1184             ),
1185         )
1186
1187     @ToolDef.from_fn
1188     def lasso():
1189         return dict(
1190             text="Select Lasso",
1191             icon="ops.generic.select_lasso",
1192             widget=None,
1193             keymap=(
1194                 ("uv.select_lasso",
1195                  dict(deselect=False),
1196                  dict(type='EVT_TWEAK_A', value='ANY')),
1197                 # ("uv.select_lasso",
1198                 #  dict(deselect=True),
1199                 #  dict(type='EVT_TWEAK_A', value='ANY', ctrl=True)),
1200             ),
1201         )
1202
1203
1204 class _defs_gpencil_paint:
1205     @staticmethod
1206     def draw_color_selector(context, layout):
1207         brush = context.active_gpencil_brush
1208         gp_settings = brush.gpencil_settings
1209         ts = context.tool_settings
1210         row = layout.row(align=True)
1211         row.prop(ts, "use_gpencil_thumbnail_list", text="", icon='IMGDISPLAY')
1212         if ts.use_gpencil_thumbnail_list is False:
1213             row.template_ID(gp_settings, "material", live_icon=True)
1214         else:
1215             row.template_greasepencil_color(gp_settings, "material", rows=3, cols=8, scale=0.8)
1216         row.prop(gp_settings, "pin_material", text="")
1217
1218     @staticmethod
1219     def draw_settings_common(context, layout, tool):
1220         ob = context.active_object
1221         if ob and ob.mode == 'GPENCIL_PAINT':
1222             brush = context.active_gpencil_brush
1223             gp_settings = brush.gpencil_settings
1224             tool_settings = context.tool_settings
1225
1226             if gp_settings.gpencil_brush_type == 'ERASE':
1227                 row = layout.row()
1228                 row.prop(brush, "size", text="Radius")
1229             elif gp_settings.gpencil_brush_type == 'FILL':
1230                 row = layout.row()
1231                 row.prop(gp_settings, "gpencil_fill_leak", text="Leak Size")
1232                 row.prop(brush, "size", text="Thickness")
1233                 row.prop(gp_settings, "gpencil_fill_simplyfy_level", text="Simplify")
1234
1235                 _defs_gpencil_paint.draw_color_selector(context, layout)
1236
1237                 row = layout.row(align=True)
1238                 row.prop(gp_settings, "gpencil_fill_draw_mode", text="")
1239                 row.prop(gp_settings, "gpencil_fill_show_boundary", text="", icon='GRID')
1240
1241             else:  # bgpsettings.gpencil_brush_type == 'DRAW':
1242                 row = layout.row(align=True)
1243                 row.prop(brush, "size", text="Radius")
1244                 row.prop(gp_settings, "use_pressure", text="", icon='STYLUS_PRESSURE')
1245                 row = layout.row(align=True)
1246                 row.prop(gp_settings, "pen_strength", slider=True)
1247                 row.prop(gp_settings, "use_strength_pressure", text="", icon='STYLUS_PRESSURE')
1248
1249                 _defs_gpencil_paint.draw_color_selector(context, layout)
1250
1251     @staticmethod
1252     def generate_from_brushes(context):
1253         return generate_from_brushes_ex(
1254             context,
1255             icon_prefix="brush.gpencil.",
1256             brush_test_attr="use_paint_grease_pencil",
1257             brush_category_attr="grease_pencil_tool",
1258             brush_category_layout=(
1259                 ('PENCIL',),
1260                 ('PEN',),
1261                 ('INK',),
1262                 ('INKNOISE',),
1263                 ('BLOCK',),
1264                 ('MARKER',),
1265                 ('FILL',),
1266                 ('SOFT',),
1267                 ('HARD',),
1268                 ('STROKE',),
1269             )
1270         )
1271
1272
1273 class _defs_gpencil_edit:
1274     @ToolDef.from_fn
1275     def bend():
1276         return dict(
1277             text="Bend",
1278             icon="ops.gpencil.edit_bend",
1279             widget=None,
1280             keymap=(
1281                 ("transform.bend",
1282                  dict(release_confirm=True),
1283                  dict(type='EVT_TWEAK_A', value='ANY')),
1284             ),
1285         )
1286
1287     @ToolDef.from_fn
1288     def mirror():
1289         return dict(
1290             text="Mirror",
1291             icon="ops.gpencil.edit_mirror",
1292             widget=None,
1293             keymap=(
1294                 ("transform.mirror",
1295                  dict(release_confirm=True),
1296                  dict(type='EVT_TWEAK_A', value='ANY')),
1297             ),
1298         )
1299
1300     @ToolDef.from_fn
1301     def shear():
1302         return dict(
1303             text="Shear",
1304             icon="ops.gpencil.edit_shear",
1305             widget=None,
1306             keymap=(
1307                 ("transform.shear",
1308                  dict(release_confirm=True),
1309                  dict(type='EVT_TWEAK_A', value='ANY')),
1310             ),
1311         )
1312
1313     @ToolDef.from_fn
1314     def tosphere():
1315         return dict(
1316             text="To Sphere",
1317             icon="ops.gpencil.edit_to_sphere",
1318             widget=None,
1319             keymap=(
1320                 ("transform.tosphere",
1321                  dict(release_confirm=True),
1322                  dict(type='EVT_TWEAK_A', value='ANY')),
1323             ),
1324         )
1325
1326
1327 class _defs_gpencil_sculpt:
1328     @staticmethod
1329     def draw_settings_common(context, layout, tool):
1330         ob = context.active_object
1331         if ob and ob.mode == 'GPENCIL_SCULPT':
1332             ts = context.tool_settings
1333             settings = ts.gpencil_sculpt
1334             brush = settings.brush
1335
1336             layout.prop(brush, "size", slider=True)
1337
1338             row = layout.row(align=True)
1339             row.prop(brush, "strength", slider=True)
1340             row.prop(brush, "use_pressure_strength", text="")
1341             row.separator()
1342             row.prop(ts.gpencil_sculpt, "use_select_mask", text="")
1343
1344     @ToolDef.from_fn
1345     def smooth():
1346         def draw_settings(context, layout, tool):
1347             _defs_gpencil_sculpt.draw_settings_common(context, layout, tool)
1348
1349         return dict(
1350             text="Smooth",
1351             icon="ops.gpencil.sculpt_smooth",
1352             widget=None,
1353             keymap=(
1354                 ("gpencil.brush_paint",
1355                  dict(mode='SMOOTH', wait_for_input=False),
1356                  dict(type='EVT_TWEAK_A', value='ANY')),
1357             ),
1358             draw_settings=draw_settings,
1359         )
1360
1361     @ToolDef.from_fn
1362     def thickness():
1363         def draw_settings(context, layout, tool):
1364             _defs_gpencil_sculpt.draw_settings_common(context, layout, tool)
1365
1366         return dict(
1367             text="Thickness",
1368             icon="ops.gpencil.sculpt_thickness",
1369             widget=None,
1370             keymap=(
1371                 ("gpencil.brush_paint",
1372                  dict(mode='THICKNESS', wait_for_input=False),
1373                  dict(type='EVT_TWEAK_A', value='ANY')),
1374             ),
1375             draw_settings=draw_settings,
1376         )
1377
1378     @ToolDef.from_fn
1379     def strength():
1380         def draw_settings(context, layout, tool):
1381             _defs_gpencil_sculpt.draw_settings_common(context, layout, tool)
1382
1383         return dict(
1384             text="Strength",
1385             icon="ops.gpencil.sculpt_strength",
1386             widget=None,
1387             keymap=(
1388                 ("gpencil.brush_paint",
1389                  dict(mode='STRENGTH', wait_for_input=False),
1390                  dict(type='EVT_TWEAK_A', value='ANY')),
1391             ),
1392             draw_settings=draw_settings,
1393         )
1394
1395     @ToolDef.from_fn
1396     def grab():
1397         def draw_settings(context, layout, tool):
1398             _defs_gpencil_sculpt.draw_settings_common(context, layout, tool)
1399
1400         return dict(
1401             text="Grab",
1402             icon="ops.gpencil.sculpt_grab",
1403             widget=None,
1404             keymap=(
1405                 ("gpencil.brush_paint",
1406                  dict(mode='GRAB', wait_for_input=False),
1407                  dict(type='EVT_TWEAK_A', value='ANY')),
1408             ),
1409             draw_settings=draw_settings,
1410         )
1411
1412     @ToolDef.from_fn
1413     def push():
1414         def draw_settings(context, layout, tool):
1415             _defs_gpencil_sculpt.draw_settings_common(context, layout, tool)
1416
1417         return dict(
1418             text="Push",
1419             icon="ops.gpencil.sculpt_push",
1420             widget=None,
1421             keymap=(
1422                 ("gpencil.brush_paint",
1423                  dict(mode='PUSH', wait_for_input=False),
1424                  dict(type='EVT_TWEAK_A', value='ANY')),
1425             ),
1426             draw_settings=draw_settings,
1427         )
1428
1429     @ToolDef.from_fn
1430     def twist():
1431         def draw_settings(context, layout, tool):
1432             _defs_gpencil_sculpt.draw_settings_common(context, layout, tool)
1433
1434         return dict(
1435             text="Twist",
1436             icon="ops.gpencil.sculpt_twist",
1437             widget=None,
1438             keymap=(
1439                 ("gpencil.brush_paint",
1440                  dict(mode='TWIST', wait_for_input=False),
1441                  dict(type='EVT_TWEAK_A', value='ANY')),
1442             ),
1443             draw_settings=draw_settings,
1444         )
1445
1446     @ToolDef.from_fn
1447     def pinch():
1448         def draw_settings(context, layout, tool):
1449             _defs_gpencil_sculpt.draw_settings_common(context, layout, tool)
1450
1451         return dict(
1452             text="Pinch",
1453             icon="ops.gpencil.sculpt_pinch",
1454             widget=None,
1455             keymap=(
1456                 ("gpencil.brush_paint",
1457                  dict(mode='PINCH', wait_for_input=False),
1458                  dict(type='EVT_TWEAK_A', value='ANY')),
1459             ),
1460             draw_settings=draw_settings,
1461         )
1462
1463     @ToolDef.from_fn
1464     def randomize():
1465         def draw_settings(context, layout, tool):
1466             _defs_gpencil_sculpt.draw_settings_common(context, layout, tool)
1467
1468         return dict(
1469             text="Randomize",
1470             icon="ops.gpencil.sculpt_randomize",
1471             widget=None,
1472             keymap=(
1473                 ("gpencil.brush_paint",
1474                  dict(mode='RANDOMIZE', wait_for_input=False),
1475                  dict(type='EVT_TWEAK_A', value='ANY')),
1476             ),
1477             draw_settings=draw_settings,
1478         )
1479
1480     @ToolDef.from_fn
1481     def clone():
1482         def draw_settings(context, layout, tool):
1483             _defs_gpencil_sculpt.draw_settings_common(context, layout, tool)
1484
1485         return dict(
1486             text="Clone",
1487             icon="ops.gpencil.sculpt_clone",
1488             widget=None,
1489             keymap=(
1490                 ("gpencil.brush_paint",
1491                  dict(mode='CLONE', wait_for_input=False),
1492                  dict(type='EVT_TWEAK_A', value='ANY')),
1493             ),
1494             draw_settings=draw_settings,
1495         )
1496
1497
1498 class _defs_gpencil_weight:
1499     @staticmethod
1500     def draw_settings_common(context, layout, tool):
1501         ob = context.active_object
1502         if ob and ob.mode == 'GPENCIL_WEIGHT':
1503             settings = context.tool_settings.gpencil_sculpt
1504             brush = settings.brush
1505
1506             layout.prop(brush, "size", slider=True)
1507
1508             row = layout.row(align=True)
1509             row.prop(brush, "strength", slider=True)
1510             row.prop(brush, "use_pressure_strength", text="")
1511
1512     @ToolDef.from_fn
1513     def paint():
1514         def draw_settings(context, layout, tool):
1515             _defs_gpencil_weight.draw_settings_common(context, layout, tool)
1516
1517         return dict(
1518             text="Draw",
1519             icon="ops.gpencil.sculpt_weight",
1520             widget=None,
1521             keymap=(
1522                 ("gpencil.brush_paint",
1523                  dict(mode='WEIGHT', wait_for_input=False),
1524                  dict(type='EVT_TWEAK_A', value='ANY')),
1525             ),
1526             draw_settings=draw_settings,
1527         )
1528
1529
1530 class IMAGE_PT_tools_active(ToolSelectPanelHelper, Panel):
1531     bl_space_type = 'IMAGE_EDITOR'
1532     bl_region_type = 'TOOLS'
1533     bl_category = "Tools"
1534     bl_label = "Tools"  # not visible
1535     bl_options = {'HIDE_HEADER'}
1536
1537     # Satisfy the 'ToolSelectPanelHelper' API.
1538     keymap_prefix = "Image Editor Tool:"
1539
1540     @classmethod
1541     def tools_from_context(cls, context, mode=None):
1542         if mode is None:
1543             if context.space_data is None:
1544                 mode = 'VIEW'
1545             else:
1546                 mode = context.space_data.mode
1547         for tools in (cls._tools[None], cls._tools.get(mode, ())):
1548             for item in tools:
1549                 if not (type(item) is ToolDef) and callable(item):
1550                     yield from item(context)
1551                 else:
1552                     yield item
1553
1554     @classmethod
1555     def tools_all(cls):
1556         yield from cls._tools.items()
1557
1558     # for reuse
1559     _tools_select = (
1560         (
1561             _defs_uv_select.border,
1562             _defs_uv_select.circle,
1563             _defs_uv_select.lasso,
1564         ),
1565     )
1566
1567     _tools_annotate = (
1568         (
1569             _defs_annotate_image.scribble,
1570             _defs_annotate_image.line,
1571             _defs_annotate_image.poly,
1572             _defs_annotate_image.eraser,
1573         ),
1574     )
1575
1576     _tools = {
1577         None: [
1578             # for all modes
1579         ],
1580         'VIEW': [
1581             *_tools_select,
1582             *_tools_annotate,
1583         ],
1584         'MASK': [
1585             None,
1586         ],
1587         'PAINT': [
1588             _defs_texture_paint.generate_from_brushes,
1589         ],
1590     }
1591
1592
1593 class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
1594     bl_space_type = 'VIEW_3D'
1595     bl_region_type = 'TOOLS'
1596     bl_category = "Tools"
1597     bl_label = "Tools"  # not visible
1598     bl_options = {'HIDE_HEADER'}
1599
1600     # Satisfy the 'ToolSelectPanelHelper' API.
1601     keymap_prefix = "3D View Tool:"
1602
1603     @classmethod
1604     def tools_from_context(cls, context, mode=None):
1605         if mode is None:
1606             mode = context.mode
1607         for tools in (cls._tools[None], cls._tools.get(mode, ())):
1608             for item in tools:
1609                 if not (type(item) is ToolDef) and callable(item):
1610                     yield from item(context)
1611                 else:
1612                     yield item
1613
1614     @classmethod
1615     def tools_all(cls):
1616         yield from cls._tools.items()
1617
1618     # for reuse
1619     _tools_transform = (
1620         _defs_transform.transform,
1621         _defs_transform.translate,
1622         _defs_transform.rotate,
1623         (
1624             _defs_transform.scale,
1625             _defs_transform.scale_cage,
1626         ),
1627     )
1628
1629     _tools_select = (
1630         (
1631             _defs_view3d_select.border,
1632             _defs_view3d_select.circle,
1633             _defs_view3d_select.lasso,
1634         ),
1635     )
1636
1637     _tools_annotate = (
1638         (
1639             _defs_annotate_view3d.scribble,
1640             _defs_annotate_view3d.line,
1641             _defs_annotate_view3d.poly,
1642             _defs_annotate_view3d.eraser,
1643         ),
1644         _defs_view3d_generic.ruler,
1645     )
1646
1647     _tools = {
1648         None: [
1649             # Don't use this! because of paint modes.
1650             # _defs_view3d_generic.cursor,
1651             # End group.
1652         ],
1653         'OBJECT': [
1654             _defs_view3d_generic.cursor,
1655             *_tools_select,
1656             None,
1657             *_tools_transform,
1658             None,
1659             *_tools_annotate,
1660         ],
1661         'POSE': [
1662             _defs_view3d_generic.cursor,
1663             *_tools_select,
1664             None,
1665             *_tools_transform,
1666             None,
1667             *_tools_annotate,
1668             None,
1669             (
1670                 _defs_pose.breakdown,
1671                 _defs_pose.push,
1672                 _defs_pose.relax,
1673             ),
1674         ],
1675         'EDIT_ARMATURE': [
1676             _defs_view3d_generic.cursor,
1677             *_tools_select,
1678             None,
1679             *_tools_transform,
1680             None,
1681             *_tools_annotate,
1682             _defs_edit_armature.roll,
1683             (
1684                 _defs_edit_armature.bone_size,
1685                 _defs_edit_armature.bone_envelope,
1686             ),
1687             None,
1688             (
1689                 _defs_edit_armature.extrude,
1690                 _defs_edit_armature.extrude_cursor,
1691             ),
1692         ],
1693         'EDIT_MESH': [
1694             _defs_view3d_generic.cursor,
1695             *_tools_select,
1696             None,
1697             *_tools_transform,
1698             None,
1699             *_tools_annotate,
1700             None,
1701             _defs_edit_mesh.cube_add,
1702             None,
1703             (
1704                 _defs_edit_mesh.extrude,
1705                 _defs_edit_mesh.extrude_normals,
1706                 _defs_edit_mesh.extrude_individual,
1707                 _defs_edit_mesh.extrude_cursor,
1708             ),
1709             _defs_edit_mesh.inset,
1710             _defs_edit_mesh.bevel,
1711             (
1712                 _defs_edit_mesh.loopcut_slide,
1713                 _defs_edit_mesh.offset_edge_loops_slide,
1714             ),
1715             (
1716                 _defs_edit_mesh.knife,
1717                 _defs_edit_mesh.bisect,
1718             ),
1719             _defs_edit_mesh.poly_build,
1720             (
1721                 _defs_edit_mesh.spin,
1722                 _defs_edit_mesh.spin_duplicate,
1723             ),
1724             (
1725                 _defs_edit_mesh.vertex_smooth,
1726                 _defs_edit_mesh.vertex_randomize,
1727             ),
1728             (
1729                 _defs_edit_mesh.edge_slide,
1730                 _defs_edit_mesh.vert_slide,
1731             ),
1732             (
1733                 _defs_edit_mesh.shrink_fatten,
1734                 _defs_edit_mesh.push_pull,
1735             ),
1736             (
1737                 _defs_edit_mesh.shear,
1738                 _defs_edit_mesh.tosphere,
1739             ),
1740             (
1741                 _defs_edit_mesh.rip_region,
1742                 _defs_edit_mesh.rip_edge,
1743             ),
1744         ],
1745         'EDIT_CURVE': [
1746             _defs_view3d_generic.cursor,
1747             *_tools_select,
1748             None,
1749             *_tools_transform,
1750             None,
1751             *_tools_annotate,
1752             None,
1753             _defs_edit_curve.draw,
1754             (
1755                 _defs_edit_curve.extrude,
1756                 _defs_edit_curve.extrude_cursor,
1757             )
1758         ],
1759         'PARTICLE': [
1760             _defs_view3d_generic.cursor,
1761             _defs_particle.generate_from_brushes,
1762         ],
1763         'SCULPT': [
1764             _defs_sculpt.generate_from_brushes,
1765             None,
1766             _defs_sculpt.hide_border,
1767             _defs_sculpt.mask_border,
1768         ],
1769         'PAINT_TEXTURE': [
1770             _defs_texture_paint.generate_from_brushes,
1771         ],
1772         'PAINT_VERTEX': [
1773             _defs_vertex_paint.generate_from_brushes,
1774             None,
1775             lambda context: (
1776                 VIEW3D_PT_tools_active._tools_select
1777                 if _defs_vertex_paint.poll_select_mask(context)
1778                 else ()
1779             ),
1780         ],
1781         'PAINT_WEIGHT': [
1782             # TODO, check for mixed pose mode
1783             _defs_view3d_generic.cursor,
1784             _defs_weight_paint.generate_from_brushes,
1785             None,
1786             _defs_weight_paint.sample_weight,
1787             _defs_weight_paint.sample_weight_group,
1788             None,
1789             lambda context: (
1790                 VIEW3D_PT_tools_active._tools_select
1791                 if _defs_weight_paint.poll_select_mask(context)
1792                 else ()
1793             ),
1794             None,
1795             _defs_weight_paint.gradient,
1796         ],
1797         'GPENCIL_PAINT': [
1798             _defs_gpencil_paint.generate_from_brushes,
1799         ],
1800         'GPENCIL_EDIT': [
1801             _defs_view3d_generic.cursor,
1802             *_tools_select,
1803             None,
1804             *_tools_transform,
1805             None,
1806             _defs_gpencil_edit.bend,
1807             _defs_gpencil_edit.mirror,
1808             _defs_gpencil_edit.shear,
1809             _defs_gpencil_edit.tosphere,
1810         ],
1811         'GPENCIL_SCULPT': [
1812             _defs_gpencil_sculpt.smooth,
1813             _defs_gpencil_sculpt.thickness,
1814             _defs_gpencil_sculpt.strength,
1815             _defs_gpencil_sculpt.grab,
1816             _defs_gpencil_sculpt.push,
1817             _defs_gpencil_sculpt.twist,
1818             _defs_gpencil_sculpt.pinch,
1819             _defs_gpencil_sculpt.randomize,
1820             _defs_gpencil_sculpt.clone,
1821         ],
1822         'GPENCIL_WEIGHT': [
1823             _defs_gpencil_weight.paint,
1824         ],
1825     }
1826
1827
1828 classes = (
1829     IMAGE_PT_tools_active,
1830     VIEW3D_PT_tools_active,
1831 )
1832
1833 if __name__ == "__main__":  # only for live edit.
1834     from bpy.utils import register_class
1835     for cls in classes:
1836         register_class(cls)