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