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