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