UI: move gizmo popover next to the overlay buttons
[blender.git] / release / scripts / startup / bl_ui / space_view3d.py
1 # ##### BEGIN GPL LICENSE BLOCK #####
2 #
3 #  This program is free software; you can redistribute it and/or
4 #  modify it under the terms of the GNU General Public License
5 #  as published by the Free Software Foundation; either version 2
6 #  of the License, or (at your option) any later version.
7 #
8 #  This program is distributed in the hope that it will be useful,
9 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 #  GNU General Public License for more details.
12 #
13 #  You should have received a copy of the GNU General Public License
14 #  along with this program; if not, write to the Free Software Foundation,
15 #  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 #
17 # ##### END GPL LICENSE BLOCK #####
18
19 # <pep8 compliant>
20 import bpy
21 from bpy.types import (
22     Header,
23     Menu,
24     Panel,
25 )
26 from .properties_paint_common import (
27     UnifiedPaintPanel,
28 )
29 from .properties_grease_pencil_common import (
30     AnnotationDataPanel,
31     AnnotationOnionSkin,
32     GreasePencilMaterialsPanel,
33 )
34 from bpy.app.translations import contexts as i18n_contexts
35
36
37 class VIEW3D_HT_header(Header):
38     bl_space_type = 'VIEW_3D'
39
40     def draw(self, context):
41         layout = self.layout
42
43         view = context.space_data
44         shading = view.shading
45         # mode_string = context.mode
46         obj = context.active_object
47         overlay = view.overlay
48         tool_settings = context.tool_settings
49
50         row = layout.row(align=True)
51         row.template_header()
52
53         object_mode = 'OBJECT' if obj is None else obj.mode
54         has_pose_mode = (
55             (object_mode == 'POSE') or
56             (object_mode == 'WEIGHT_PAINT' and context.pose_object is not None)
57         )
58
59         # Note: This is actually deadly in case enum_items have to be dynamically generated
60         #       (because internal RNA array iterator will free everything immediately...).
61         # XXX This is an RNA internal issue, not sure how to fix it.
62         # Note: Tried to add an accessor to get translated UI strings instead of manual call
63         #       to pgettext_iface below, but this fails because translated enumitems
64         #       are always dynamically allocated.
65         act_mode_item = bpy.types.Object.bl_rna.properties["mode"].enum_items[object_mode]
66         act_mode_i18n_context = bpy.types.Object.bl_rna.properties["mode"].translation_context
67
68         row.separator()
69
70         sub = row.row()
71         sub.ui_units_x = 5.5
72         sub.operator_menu_enum("object.mode_set", "mode",
73                                text=bpy.app.translations.pgettext_iface(act_mode_item.name, act_mode_i18n_context),
74                                icon=act_mode_item.icon)
75         del act_mode_item
76
77         layout.template_header_3D_mode()
78
79         # Contains buttons like Mode, Pivot, Layer, Mesh Select Mode...
80         if obj:
81             # Particle edit
82             if object_mode == 'PARTICLE_EDIT':
83                 row = layout.row()
84                 row.prop(tool_settings.particle_edit, "select_mode", text="", expand=True)
85
86         # Grease Pencil
87         if obj and obj.type == 'GPENCIL' and context.gpencil_data:
88             gpd = context.gpencil_data
89
90             if gpd.is_stroke_paint_mode:
91                 row = layout.row()
92                 sub = row.row(align=True)
93                 sub.prop(tool_settings, "use_gpencil_draw_onback", text="", icon='MOD_OPACITY')
94                 sub.separator(factor=0.4)
95                 sub.prop(tool_settings, "use_gpencil_weight_data_add", text="", icon='WPAINT_HLT')
96                 sub.separator(factor=0.4)
97                 sub.prop(tool_settings, "use_gpencil_draw_additive", text="", icon='FREEZE')
98
99             if gpd.use_stroke_edit_mode:
100                 row = layout.row(align=True)
101                 row.prop(tool_settings, "gpencil_selectmode", text="", expand=True)
102
103             if gpd.use_stroke_edit_mode or gpd.is_stroke_sculpt_mode or gpd.is_stroke_weight_mode:
104                 row = layout.row(align=True)
105
106                 if gpd.is_stroke_sculpt_mode:
107                     row.prop(tool_settings.gpencil_sculpt, "use_select_mask", text="")
108                     row.separator()
109
110                 row.prop(gpd, "use_multiedit", text="", icon='GP_MULTIFRAME_EDITING')
111
112                 sub = row.row(align=True)
113                 sub.active = gpd.use_multiedit
114                 sub.popover(
115                     panel="VIEW3D_PT_gpencil_multi_frame",
116                     text="Multiframe",
117                 )
118
119             if gpd.use_stroke_edit_mode:
120                 row = layout.row(align=True)
121                 row.prop(tool_settings.gpencil_sculpt, "use_select_mask", text="")
122
123                 row.popover(
124                     panel="VIEW3D_PT_tools_grease_pencil_interpolate",
125                     text="Interpolate",
126                 )
127
128         VIEW3D_MT_editor_menus.draw_collapsible(context, layout)
129
130         layout.separator_spacer()
131
132         # Mode & Transform Settings
133         scene = context.scene
134
135         # Orientation
136         if object_mode in {'OBJECT', 'EDIT', 'EDIT_GPENCIL'} or has_pose_mode:
137             orient_slot = scene.transform_orientation_slots[0]
138             row = layout.row(align=True)
139
140             sub = row.row()
141             sub.ui_units_x = 4
142             sub.prop_with_popover(
143                 orient_slot,
144                 "type",
145                 text="",
146                 panel="VIEW3D_PT_transform_orientations",
147             )
148
149         # Pivot
150         if object_mode in {'OBJECT', 'EDIT', 'EDIT_GPENCIL', 'SCULPT_GPENCIL'} or has_pose_mode:
151             layout.prop_with_popover(
152                 tool_settings,
153                 "transform_pivot_point",
154                 text="",
155                 icon_only=True,
156                 panel="VIEW3D_PT_pivot_point",
157             )
158
159         # Snap
160         show_snap = False
161         if obj is None:
162             show_snap = True
163         else:
164             if (object_mode not in {
165                     'SCULPT', 'VERTEX_PAINT', 'WEIGHT_PAINT', 'TEXTURE_PAINT',
166                     'PAINT_GPENCIL', 'SCULPT_GPENCIL', 'WEIGHT_GPENCIL'
167             }) or has_pose_mode:
168                 show_snap = True
169             else:
170
171                 from .properties_paint_common import UnifiedPaintPanel
172                 paint_settings = UnifiedPaintPanel.paint_settings(context)
173
174                 if paint_settings:
175                     brush = paint_settings.brush
176                     if brush and brush.stroke_method == 'CURVE':
177                         show_snap = True
178
179         if show_snap:
180             snap_items = bpy.types.ToolSettings.bl_rna.properties["snap_elements"].enum_items
181             snap_elements = tool_settings.snap_elements
182             if len(snap_elements) == 1:
183                 text = ""
184                 for elem in snap_elements:
185                     icon = snap_items[elem].icon
186                     break
187             else:
188                 text = "Mix"
189                 icon = 'NONE'
190             del snap_items, snap_elements
191
192             row = layout.row(align=True)
193             row.prop(tool_settings, "use_snap", text="")
194
195             sub = row.row(align=True)
196             sub.popover(
197                 panel="VIEW3D_PT_snapping",
198                 icon=icon,
199                 text=text,
200             )
201
202         # Proportional editing
203         gpd = context.gpencil_data
204         if object_mode in {'EDIT', 'PARTICLE_EDIT'}:
205             row = layout.row(align=True)
206             row.prop(tool_settings, "proportional_edit", icon_only=True)
207             sub = row.row(align=True)
208             sub.active = tool_settings.proportional_edit != 'DISABLED'
209             sub.prop(tool_settings, "proportional_edit_falloff", icon_only=True)
210
211         elif object_mode == 'OBJECT':
212             row = layout.row(align=True)
213             row.prop(tool_settings, "use_proportional_edit_objects", icon_only=True)
214             sub = row.row(align=True)
215             sub.active = tool_settings.use_proportional_edit_objects
216             sub.prop(tool_settings, "proportional_edit_falloff", icon_only=True)
217
218         elif gpd is not None and obj.type == 'GPENCIL':
219             if gpd.use_stroke_edit_mode or gpd.is_stroke_sculpt_mode:
220                 row = layout.row(align=True)
221                 row.prop(tool_settings, "proportional_edit", icon_only=True)
222
223                 sub = row.row(align=True)
224                 sub.active = tool_settings.proportional_edit != 'DISABLED'
225                 sub.prop(tool_settings, "proportional_edit_falloff", icon_only=True)
226
227         # grease pencil
228         if object_mode == 'PAINT_GPENCIL':
229             layout.prop_with_popover(
230                 tool_settings,
231                 "gpencil_stroke_placement_view3d",
232                 text="",
233                 panel="VIEW3D_PT_gpencil_origin",
234             )
235
236         if object_mode in {'PAINT_GPENCIL', 'SCULPT_GPENCIL'}:
237             layout.prop_with_popover(
238                 tool_settings.gpencil_sculpt,
239                 "lock_axis",
240                 text="",
241                 panel="VIEW3D_PT_gpencil_lock",
242             )
243
244         if object_mode == 'PAINT_GPENCIL':
245             # FIXME: this is bad practice!
246             # Tool options are to be displayed in the topbar.
247             if context.workspace.tools.from_space_view3d_mode(object_mode).idname == "builtin_brush.Draw":
248                 settings = tool_settings.gpencil_sculpt.guide
249                 row = layout.row(align=True)
250                 row.prop(settings, "use_guide", text="", icon='GRID')
251                 sub = row.row(align=True)
252                 sub.active = settings.use_guide
253                 sub.popover(
254                     panel="VIEW3D_PT_gpencil_guide",
255                     text="Guides",
256                 )
257
258         layout.separator_spacer()
259
260         # Collection Visibility
261         layout.popover(
262             panel="VIEW3D_PT_collections",
263             icon='GROUP',
264             text="",
265         )
266
267         # Viewport Settings
268         layout.popover(
269             panel="VIEW3D_PT_object_type_visibility",
270             icon_value=view.icon_from_show_object_viewport,
271             text="",
272         )
273
274         # Gizmo toggle & popover.
275         row = layout.row(align=True)
276         # FIXME: place-holder icon.
277         row.prop(view, "show_gizmo", text="", toggle=True, icon='EMPTY_DATA')
278         sub = row.row(align=True)
279         sub.active = view.show_gizmo
280         sub.popover(
281             panel="VIEW3D_PT_gizmo_display",
282             text="",
283         )
284
285         # Overlay toggle & popover.
286         row = layout.row(align=True)
287         row.prop(overlay, "show_overlays", icon='OVERLAY', text="")
288         sub = row.row(align=True)
289         sub.active = overlay.show_overlays
290         sub.popover(panel="VIEW3D_PT_overlay", text="")
291
292         row = layout.row()
293         row.active = (shading.type in {'WIREFRAME', 'SOLID'}) or object_mode in {'EDIT'}
294
295         if shading.type == 'WIREFRAME':
296             row.prop(shading, "show_xray_wireframe", text="", icon='XRAY')
297         else:
298             row.prop(shading, "show_xray", text="", icon='XRAY')
299
300         row = layout.row(align=True)
301         row.prop(shading, "type", text="", expand=True)
302         sub = row.row(align=True)
303         # TODO, currently render shading type ignores mesh two-side, until it's supported
304         # show the shading popover which shows double-sided option.
305
306         # sub.enabled = shading.type != 'RENDERED'
307         sub.popover(panel="VIEW3D_PT_shading", text="")
308
309
310 class VIEW3D_MT_editor_menus(Menu):
311     bl_label = ""
312
313     def draw(self, context):
314         layout = self.layout
315         obj = context.active_object
316         mode_string = context.mode
317         edit_object = context.edit_object
318         gp_edit = obj and obj.mode in {'EDIT_GPENCIL', 'PAINT_GPENCIL', 'SCULPT_GPENCIL', 'WEIGHT_GPENCIL'}
319
320         layout.menu("VIEW3D_MT_view")
321
322         # Select Menu
323         if gp_edit:
324             if mode_string not in {'PAINT_GPENCIL', 'WEIGHT_GPENCIL'}:
325                 layout.menu("VIEW3D_MT_select_gpencil")
326         elif mode_string in {'PAINT_WEIGHT', 'PAINT_VERTEX', 'PAINT_TEXTURE'}:
327             mesh = obj.data
328             if mesh.use_paint_mask:
329                 layout.menu("VIEW3D_MT_select_paint_mask")
330             elif mesh.use_paint_mask_vertex and mode_string in {'PAINT_WEIGHT', 'PAINT_VERTEX'}:
331                 layout.menu("VIEW3D_MT_select_paint_mask_vertex")
332         elif mode_string != 'SCULPT':
333             layout.menu("VIEW3D_MT_select_%s" % mode_string.lower())
334
335         if gp_edit:
336             pass
337         elif mode_string == 'OBJECT':
338             layout.menu("VIEW3D_MT_add", text="Add")
339         elif mode_string == 'EDIT_MESH':
340             layout.menu("VIEW3D_MT_mesh_add", text="Add")
341         elif mode_string == 'EDIT_CURVE':
342             layout.menu("VIEW3D_MT_curve_add", text="Add")
343         elif mode_string == 'EDIT_SURFACE':
344             layout.menu("VIEW3D_MT_surface_add", text="Add")
345         elif mode_string == 'EDIT_METABALL':
346             layout.menu("VIEW3D_MT_metaball_add", text="Add")
347         elif mode_string == 'EDIT_ARMATURE':
348             layout.menu("TOPBAR_MT_edit_armature_add", text="Add")
349
350         if gp_edit:
351             if obj and obj.mode == 'PAINT_GPENCIL':
352                 layout.menu("VIEW3D_MT_paint_gpencil")
353             elif obj and obj.mode == 'EDIT_GPENCIL':
354                 layout.menu("VIEW3D_MT_edit_gpencil")
355             elif obj and obj.mode == 'WEIGHT_GPENCIL':
356                 layout.menu("VIEW3D_MT_weight_gpencil")
357
358         elif edit_object:
359             layout.menu("VIEW3D_MT_edit_%s" % edit_object.type.lower())
360
361             if mode_string == 'EDIT_MESH':
362                 layout.menu("VIEW3D_MT_edit_mesh_vertices")
363                 layout.menu("VIEW3D_MT_edit_mesh_edges")
364                 layout.menu("VIEW3D_MT_edit_mesh_faces")
365                 layout.menu("VIEW3D_MT_uv_map", text="UV")
366             elif mode_string in {'EDIT_CURVE', 'EDIT_SURFACE'}:
367                 layout.menu("VIEW3D_MT_edit_curve_ctrlpoints")
368                 layout.menu("VIEW3D_MT_edit_curve_segments")
369
370         elif obj:
371             if mode_string != 'PAINT_TEXTURE':
372                 layout.menu("VIEW3D_MT_%s" % mode_string.lower())
373             if mode_string in {'SCULPT', 'PAINT_VERTEX', 'PAINT_WEIGHT', 'PAINT_TEXTURE'}:
374                 layout.menu("VIEW3D_MT_brush")
375             if mode_string == 'SCULPT':
376                 layout.menu("VIEW3D_MT_hide_mask")
377         else:
378             layout.menu("VIEW3D_MT_object")
379
380
381 # ********** Menu **********
382
383
384 # ********** Utilities **********
385
386
387 class ShowHideMenu:
388     bl_label = "Show/Hide"
389     _operator_name = ""
390
391     def draw(self, context):
392         layout = self.layout
393
394         layout.operator("%s.reveal" % self._operator_name)
395         layout.operator("%s.hide" % self._operator_name, text="Hide Selected").unselected = False
396         layout.operator("%s.hide" % self._operator_name, text="Hide Unselected").unselected = True
397
398
399 # Standard transforms which apply to all cases
400 # NOTE: this doesn't seem to be able to be used directly
401 class VIEW3D_MT_transform_base(Menu):
402     bl_label = "Transform"
403     bl_category = "View"
404
405     # TODO: get rid of the custom text strings?
406     def draw(self, context):
407         layout = self.layout
408
409         layout.operator("transform.translate")
410         layout.operator("transform.rotate")
411         layout.operator("transform.resize", text="Scale")
412
413         layout.separator()
414
415         layout.operator("transform.tosphere", text="To Sphere")
416         layout.operator("transform.shear", text="Shear")
417         layout.operator("transform.bend", text="Bend")
418         layout.operator("transform.push_pull", text="Push/Pull")
419
420         if context.mode != 'OBJECT':
421             layout.operator("transform.vertex_warp", text="Warp")
422             layout.operator("transform.vertex_random", text="Randomize")
423
424
425 # Generic transform menu - geometry types
426 class VIEW3D_MT_transform(VIEW3D_MT_transform_base):
427     def draw(self, context):
428         # base menu
429         VIEW3D_MT_transform_base.draw(self, context)
430
431         # generic...
432         layout = self.layout
433         if context.mode == 'EDIT_MESH':
434             layout.operator("transform.shrink_fatten", text="Shrink Fatten")
435         elif context.mode == 'EDIT_CURVE':
436             layout.operator("transform.transform", text="Radius").mode = 'CURVE_SHRINKFATTEN'
437
438         layout.separator()
439
440         layout.operator("transform.translate", text="Move Texture Space").texture_space = True
441         layout.operator("transform.resize", text="Scale Texture Space").texture_space = True
442
443
444 # Object-specific extensions to Transform menu
445 class VIEW3D_MT_transform_object(VIEW3D_MT_transform_base):
446     def draw(self, context):
447         layout = self.layout
448
449         # base menu
450         VIEW3D_MT_transform_base.draw(self, context)
451
452         # object-specific option follow...
453         layout.separator()
454
455         layout.operator("transform.translate", text="Move Texture Space").texture_space = True
456         layout.operator("transform.resize", text="Scale Texture Space").texture_space = True
457
458         layout.separator()
459
460         layout.operator_context = 'EXEC_REGION_WIN'
461         # XXX see alignmenu() in edit.c of b2.4x to get this working
462         layout.operator("transform.transform", text="Align to Transform Orientation").mode = 'ALIGN'
463
464         layout.separator()
465
466         layout.operator("object.randomize_transform")
467         layout.operator("object.align")
468
469         # TODO: there is a strange context bug here.
470         """
471         layout.operator_context = 'INVOKE_REGION_WIN'
472         layout.operator("object.transform_axis_target")
473         """
474
475
476 # Armature EditMode extensions to Transform menu
477 class VIEW3D_MT_transform_armature(VIEW3D_MT_transform_base):
478     def draw(self, context):
479         layout = self.layout
480
481         # base menu
482         VIEW3D_MT_transform_base.draw(self, context)
483
484         # armature specific extensions follow...
485         obj = context.object
486         if obj.type == 'ARMATURE' and obj.mode in {'EDIT', 'POSE'}:
487             if obj.data.display_type == 'BBONE':
488                 layout.separator()
489
490                 layout.operator("transform.transform", text="Scale BBone").mode = 'BONE_SIZE'
491             elif obj.data.display_type == 'ENVELOPE':
492                 layout.separator()
493
494                 layout.operator("transform.transform", text="Scale Envelope Distance").mode = 'BONE_SIZE'
495                 layout.operator("transform.transform", text="Scale Radius").mode = 'BONE_ENVELOPE'
496
497         if context.edit_object and context.edit_object.type == 'ARMATURE':
498             layout.separator()
499
500             layout.operator("armature.align")
501
502
503 class VIEW3D_MT_mirror(Menu):
504     bl_label = "Mirror"
505
506     def draw(self, context):
507         layout = self.layout
508
509         layout.operator("transform.mirror", text="Interactive Mirror")
510
511         layout.separator()
512
513         layout.operator_context = 'EXEC_REGION_WIN'
514
515         for (space_name, space_id) in (("Global", 'GLOBAL'), ("Local", 'LOCAL')):
516             for axis_index, axis_name in enumerate("XYZ"):
517                 props = layout.operator("transform.mirror", text=f"{axis_name!s} {space_name!s}")
518                 props.constraint_axis[axis_index] = True
519                 props.orient_type = 'GLOBAL'
520
521             if space_id == 'GLOBAL':
522                 layout.separator()
523
524
525 class VIEW3D_MT_snap(Menu):
526     bl_label = "Snap"
527
528     def draw(self, context):
529         layout = self.layout
530
531         layout.operator("view3d.snap_selected_to_grid", text="Selection to Grid")
532         layout.operator("view3d.snap_selected_to_cursor", text="Selection to Cursor").use_offset = False
533         layout.operator("view3d.snap_selected_to_cursor", text="Selection to Cursor (Keep Offset)").use_offset = True
534         layout.operator("view3d.snap_selected_to_active", text="Selection to Active")
535
536         layout.separator()
537
538         layout.operator("view3d.snap_cursor_to_selected", text="Cursor to Selected")
539         layout.operator("view3d.snap_cursor_to_center", text="Cursor to World Origin")
540         layout.operator("view3d.snap_cursor_to_grid", text="Cursor to Grid")
541         layout.operator("view3d.snap_cursor_to_active", text="Cursor to Active")
542
543
544 class VIEW3D_MT_uv_map(Menu):
545     bl_label = "UV Mapping"
546
547     def draw(self, context):
548         layout = self.layout
549
550         layout.operator("uv.unwrap")
551
552         layout.operator_context = 'INVOKE_DEFAULT'
553         layout.operator("uv.smart_project")
554         layout.operator("uv.lightmap_pack")
555         layout.operator("uv.follow_active_quads")
556
557         layout.separator()
558
559         layout.operator_context = 'EXEC_REGION_WIN'
560         layout.operator("uv.cube_project")
561         layout.operator("uv.cylinder_project")
562         layout.operator("uv.sphere_project")
563
564         layout.separator()
565
566         layout.operator_context = 'INVOKE_REGION_WIN'
567         layout.operator("uv.project_from_view").scale_to_bounds = False
568         layout.operator("uv.project_from_view", text="Project from View (Bounds)").scale_to_bounds = True
569
570         layout.separator()
571
572         layout.operator("mesh.mark_seam").clear = False
573         layout.operator("mesh.mark_seam", text="Clear Seam").clear = True
574
575         layout.separator()
576
577         layout.operator("uv.reset")
578
579
580 # ********** View menus **********
581
582
583 class VIEW3D_MT_view(Menu):
584     bl_label = "View"
585
586     def draw(self, context):
587         layout = self.layout
588         view = context.space_data
589
590         layout.operator("view3d.toolshelf", icon='MENU_PANEL')
591         layout.operator("view3d.properties", icon='MENU_PANEL')
592
593         layout.separator()
594
595         layout.operator("view3d.view_selected", text="Frame Selected").use_all_regions = False
596         if view.region_quadviews:
597             layout.operator("view3d.view_selected", text="Frame Selected (Quad View)").use_all_regions = True
598
599         layout.operator("view3d.view_all", text="Frame All").center = False
600         layout.operator("view3d.view_persportho", text="Perspective/Orthographic")
601         layout.menu("VIEW3D_MT_view_local")
602
603         layout.separator()
604
605         layout.menu("VIEW3D_MT_view_cameras", text="Cameras")
606
607         layout.separator()
608         layout.menu("VIEW3D_MT_view_viewpoint")
609         layout.menu("VIEW3D_MT_view_navigation")
610         layout.menu("VIEW3D_MT_view_align")
611
612         layout.separator()
613
614         layout.operator_context = 'INVOKE_REGION_WIN'
615         layout.menu("VIEW3D_MT_view_regions", text="View Regions")
616
617         layout.separator()
618
619         layout.operator("screen.animation_play", text="Play Animation")
620
621         layout.separator()
622
623         layout.operator("render.opengl", text="Viewport Render Image", icon='RENDER_STILL')
624         layout.operator("render.opengl", text="Viewport Render Animation", icon='RENDER_ANIMATION').animation = True
625
626         layout.separator()
627
628         layout.menu("INFO_MT_area")
629
630
631 class VIEW3D_MT_view_local(Menu):
632     bl_label = "Local View"
633
634     def draw(self, context):
635         layout = self.layout
636
637         layout.operator("view3d.localview", text="Toggle Local View")
638         layout.operator("view3d.localview_remove_from")
639
640
641 class VIEW3D_MT_view_cameras(Menu):
642     bl_label = "Cameras"
643
644     def draw(self, context):
645         layout = self.layout
646
647         layout.operator("view3d.object_as_camera")
648         layout.operator("view3d.view_camera", text="Active Camera")
649
650
651 class VIEW3D_MT_view_viewpoint(Menu):
652     bl_label = "Viewpoint"
653
654     def draw(self, context):
655         layout = self.layout
656
657         layout.operator("view3d.view_camera", text="Camera")
658
659         layout.separator()
660
661         layout.operator("view3d.view_axis", text="Top").type = 'TOP'
662         layout.operator("view3d.view_axis", text="Bottom").type = 'BOTTOM'
663
664         layout.separator()
665
666         layout.operator("view3d.view_axis", text="Front").type = 'FRONT'
667         layout.operator("view3d.view_axis", text="Back").type = 'BACK'
668
669         layout.separator()
670
671         layout.operator("view3d.view_axis", text="Right").type = 'RIGHT'
672         layout.operator("view3d.view_axis", text="Left").type = 'LEFT'
673
674
675 class VIEW3D_MT_view_navigation(Menu):
676     bl_label = "Navigation"
677
678     def draw(self, context):
679         from math import pi
680         layout = self.layout
681
682         layout.operator_enum("view3d.view_orbit", "type")
683         props = layout.operator("view3d.view_orbit", text="Orbit Opposite")
684         props.type = 'ORBITRIGHT'
685         props.angle = pi
686
687         layout.separator()
688
689         layout.operator("view3d.view_roll", text="Roll Left").type = 'LEFT'
690         layout.operator("view3d.view_roll", text="Roll Right").type = 'RIGHT'
691
692         layout.separator()
693
694         layout.operator_enum("view3d.view_pan", "type")
695
696         layout.separator()
697
698         layout.operator("view3d.zoom", text="Zoom In").delta = 1
699         layout.operator("view3d.zoom", text="Zoom Out").delta = -1
700         layout.operator("view3d.zoom_border", text="Zoom Border...")
701         layout.operator("view3d.zoom_camera_1_to_1", text="Zoom Camera 1:1")
702
703         layout.separator()
704
705         layout.operator("view3d.fly")
706         layout.operator("view3d.walk")
707
708
709 class VIEW3D_MT_view_align(Menu):
710     bl_label = "Align View"
711
712     def draw(self, context):
713         layout = self.layout
714
715         layout.menu("VIEW3D_MT_view_align_selected")
716
717         layout.separator()
718
719         layout.operator("view3d.camera_to_view", text="Align Active Camera to View")
720         layout.operator("view3d.camera_to_view_selected", text="Align Active Camera to Selected")
721
722         layout.separator()
723
724         layout.operator("view3d.view_all", text="Center Cursor and View All").center = True
725         layout.operator("view3d.view_center_cursor")
726
727         layout.separator()
728
729         layout.operator("view3d.view_lock_to_active")
730         layout.operator("view3d.view_lock_clear")
731
732
733 class VIEW3D_MT_view_align_selected(Menu):
734     bl_label = "Align View to Active"
735
736     def draw(self, context):
737         layout = self.layout
738
739         props = layout.operator("view3d.view_axis", text="Top")
740         props.align_active = True
741         props.type = 'TOP'
742
743         props = layout.operator("view3d.view_axis", text="Bottom")
744         props.align_active = True
745         props.type = 'BOTTOM'
746
747         layout.separator()
748
749         props = layout.operator("view3d.view_axis", text="Front")
750         props.align_active = True
751         props.type = 'FRONT'
752
753         props = layout.operator("view3d.view_axis", text="Back")
754         props.align_active = True
755         props.type = 'BACK'
756
757         layout.separator()
758
759         props = layout.operator("view3d.view_axis", text="Right")
760         props.align_active = True
761         props.type = 'RIGHT'
762
763         props = layout.operator("view3d.view_axis", text="Left")
764         props.align_active = True
765         props.type = 'LEFT'
766
767
768 class VIEW3D_MT_view_regions(Menu):
769     bl_label = "View Regions"
770
771     def draw(self, context):
772         layout = self.layout
773         layout.operator("view3d.clip_border", text="Clipping Region...")
774         layout.operator("view3d.render_border", text="Render Region...")
775
776         layout.separator()
777
778         layout.operator("view3d.clear_render_border")
779
780
781 # ********** Select menus, suffix from context.mode **********
782
783 class VIEW3D_MT_select_object_more_less(Menu):
784     bl_label = "Select More/Less"
785
786     def draw(self, context):
787         layout = self.layout
788
789         layout = self.layout
790
791         layout.operator("object.select_more", text="More")
792         layout.operator("object.select_less", text="Less")
793
794         layout.separator()
795
796         props = layout.operator("object.select_hierarchy", text="Parent")
797         props.extend = False
798         props.direction = 'PARENT'
799
800         props = layout.operator("object.select_hierarchy", text="Child")
801         props.extend = False
802         props.direction = 'CHILD'
803
804         layout.separator()
805
806         props = layout.operator("object.select_hierarchy", text="Extend Parent")
807         props.extend = True
808         props.direction = 'PARENT'
809
810         props = layout.operator("object.select_hierarchy", text="Extend Child")
811         props.extend = True
812         props.direction = 'CHILD'
813
814
815 class VIEW3D_MT_select_object(Menu):
816     bl_label = "Select"
817
818     def draw(self, context):
819         layout = self.layout
820
821         layout.operator("object.select_all", text="All").action = 'SELECT'
822         layout.operator("object.select_all", text="None").action = 'DESELECT'
823         layout.operator("object.select_all", text="Invert").action = 'INVERT'
824
825         layout.separator()
826
827         layout.operator("view3d.select_box")
828         layout.operator("view3d.select_circle")
829
830         layout.separator()
831
832         layout.operator_menu_enum("object.select_by_type", "type", text="Select All by Type...")
833         layout.operator("object.select_camera", text="Select Active Camera")
834         layout.operator("object.select_mirror", text="Mirror Selection")
835         layout.operator("object.select_random", text="Select Random")
836
837         layout.separator()
838
839         layout.menu("VIEW3D_MT_select_object_more_less")
840
841         layout.separator()
842
843         layout.operator_menu_enum("object.select_grouped", "type", text="Select Grouped")
844         layout.operator_menu_enum("object.select_linked", "type", text="Select Linked")
845         layout.operator("object.select_pattern", text="Select Pattern...")
846
847
848 class VIEW3D_MT_select_pose_more_less(Menu):
849     bl_label = "Select More/Less"
850
851     def draw(self, context):
852         layout = self.layout
853
854         layout = self.layout
855
856         props = layout.operator("pose.select_hierarchy", text="Parent")
857         props.extend = False
858         props.direction = 'PARENT'
859
860         props = layout.operator("pose.select_hierarchy", text="Child")
861         props.extend = False
862         props.direction = 'CHILD'
863
864         layout.separator()
865
866         props = layout.operator("pose.select_hierarchy", text="Extend Parent")
867         props.extend = True
868         props.direction = 'PARENT'
869
870         props = layout.operator("pose.select_hierarchy", text="Extend Child")
871         props.extend = True
872         props.direction = 'CHILD'
873
874
875 class VIEW3D_MT_select_pose(Menu):
876     bl_label = "Select"
877
878     def draw(self, context):
879         layout = self.layout
880
881         layout.operator("pose.select_all", text="All").action = 'SELECT'
882         layout.operator("pose.select_all", text="None").action = 'DESELECT'
883         layout.operator("pose.select_all", text="Invert").action = 'INVERT'
884
885         layout.separator()
886
887         layout.operator("view3d.select_box")
888         layout.operator("view3d.select_circle")
889
890         layout.separator()
891
892         layout.operator("pose.select_mirror", text="Flip Active")
893
894         layout.separator()
895
896         layout.operator("pose.select_constraint_target", text="Constraint Target")
897         layout.operator("pose.select_linked", text="Linked")
898
899         layout.separator()
900
901         layout.menu("VIEW3D_MT_select_pose_more_less")
902
903         layout.separator()
904
905         layout.operator_menu_enum("pose.select_grouped", "type", text="Grouped")
906         layout.operator("object.select_pattern", text="Select Pattern...")
907
908
909 class VIEW3D_MT_select_particle(Menu):
910     bl_label = "Select"
911
912     def draw(self, context):
913         layout = self.layout
914
915         layout.operator("particle.select_all", text="All").action = 'SELECT'
916         layout.operator("particle.select_all", text="None").action = 'DESELECT'
917         layout.operator("particle.select_all", text="Invert").action = 'INVERT'
918
919         layout.separator()
920
921         layout.operator("view3d.select_box")
922         layout.operator("view3d.select_circle")
923
924         layout.separator()
925
926         layout.operator("particle.select_linked")
927
928         layout.separator()
929
930         layout.operator("particle.select_more")
931         layout.operator("particle.select_less")
932
933         layout.separator()
934
935         layout.operator("particle.select_random")
936
937         layout.separator()
938
939         layout.operator("particle.select_roots", text="Roots")
940         layout.operator("particle.select_tips", text="Tips")
941
942
943 class VIEW3D_MT_edit_mesh_select_similar(Menu):
944     bl_label = "Select Similar"
945
946     def draw(self, context):
947         layout = self.layout
948
949         layout.operator_enum("mesh.select_similar", "type")
950
951         layout.separator()
952
953         layout.operator("mesh.select_similar_region", text="Face Regions")
954
955
956 class VIEW3D_MT_edit_mesh_select_by_trait(Menu):
957     bl_label = "Select All by Trait"
958
959     def draw(self, context):
960         layout = self.layout
961         tool_settings = context.tool_settings
962         if tool_settings.mesh_select_mode[2] is False:
963             layout.operator("mesh.select_non_manifold", text="Non Manifold")
964         layout.operator("mesh.select_loose", text="Loose Geometry")
965         layout.operator("mesh.select_interior_faces", text="Interior Faces")
966         layout.operator("mesh.select_face_by_sides", text="Faces by Sides")
967
968         layout.separator()
969
970         layout.operator("mesh.select_ungrouped", text="Ungrouped Verts")
971
972
973 class VIEW3D_MT_edit_mesh_select_more_less(Menu):
974     bl_label = "Select More/Less"
975
976     def draw(self, context):
977         layout = self.layout
978
979         layout.operator("mesh.select_more", text="More")
980         layout.operator("mesh.select_less", text="Less")
981
982         layout.separator()
983
984         layout.operator("mesh.select_next_item", text="Next Active")
985         layout.operator("mesh.select_prev_item", text="Previous Active")
986
987
988 class VIEW3D_MT_edit_mesh_select_linked(Menu):
989     bl_label = "Select Linked"
990
991     def draw(self, context):
992         layout = self.layout
993
994         layout.operator("mesh.select_linked", text="Linked")
995         layout.operator("mesh.shortest_path_select", text="Shortest Path")
996         layout.operator("mesh.faces_select_linked_flat", text="Linked Flat Faces")
997
998
999 class VIEW3D_MT_edit_mesh_select_loops(Menu):
1000     bl_label = "Select Loops"
1001
1002     def draw(self, context):
1003         layout = self.layout
1004
1005         layout.operator("mesh.loop_multi_select", text="Edge Loops").ring = False
1006         layout.operator("mesh.loop_multi_select", text="Edge Rings").ring = True
1007
1008         layout.separator()
1009
1010         layout.operator("mesh.loop_to_region")
1011         layout.operator("mesh.region_to_loop")
1012
1013
1014 class VIEW3D_MT_select_edit_mesh(Menu):
1015     bl_label = "Select"
1016
1017     def draw(self, context):
1018         layout = self.layout
1019
1020         # primitive
1021         layout.operator("mesh.select_all", text="All").action = 'SELECT'
1022         layout.operator("mesh.select_all", text="None").action = 'DESELECT'
1023         layout.operator("mesh.select_all", text="Invert").action = 'INVERT'
1024
1025         layout.separator()
1026
1027         layout.operator("view3d.select_box")
1028         layout.operator("view3d.select_circle")
1029
1030         layout.separator()
1031
1032         # numeric
1033         layout.operator("mesh.select_random", text="Select Random")
1034         layout.operator("mesh.select_nth")
1035
1036         layout.separator()
1037
1038         # geometric
1039         layout.operator("mesh.edges_select_sharp", text="Select Sharp Edges")
1040
1041         layout.separator()
1042
1043         # other ...
1044         layout.menu("VIEW3D_MT_edit_mesh_select_similar")
1045
1046         layout.separator()
1047
1048         layout.menu("VIEW3D_MT_edit_mesh_select_by_trait")
1049
1050         layout.separator()
1051
1052         layout.menu("VIEW3D_MT_edit_mesh_select_more_less")
1053
1054         layout.separator()
1055
1056         layout.menu("VIEW3D_MT_edit_mesh_select_loops")
1057
1058         layout.separator()
1059
1060         layout.menu("VIEW3D_MT_edit_mesh_select_linked")
1061
1062         layout.separator()
1063
1064         layout.operator("mesh.select_axis", text="Side of Active")
1065         layout.operator("mesh.select_mirror", text="Mirror Selection")
1066
1067
1068 class VIEW3D_MT_select_edit_curve(Menu):
1069     bl_label = "Select"
1070
1071     def draw(self, context):
1072         layout = self.layout
1073
1074         layout.operator("curve.select_all", text="All").action = 'SELECT'
1075         layout.operator("curve.select_all", text="None").action = 'DESELECT'
1076         layout.operator("curve.select_all", text="Invert").action = 'INVERT'
1077
1078         layout.separator()
1079
1080         layout.operator("view3d.select_box")
1081         layout.operator("view3d.select_circle")
1082
1083         layout.separator()
1084
1085         layout.operator("curve.select_random")
1086         layout.operator("curve.select_nth")
1087         layout.operator("curve.select_linked", text="Select Linked")
1088         layout.operator("curve.select_similar", text="Select Similar")
1089
1090         layout.separator()
1091
1092         layout.operator("curve.de_select_first")
1093         layout.operator("curve.de_select_last")
1094         layout.operator("curve.select_next")
1095         layout.operator("curve.select_previous")
1096
1097         layout.separator()
1098
1099         layout.operator("curve.select_more")
1100         layout.operator("curve.select_less")
1101
1102
1103 class VIEW3D_MT_select_edit_surface(Menu):
1104     bl_label = "Select"
1105
1106     def draw(self, context):
1107         layout = self.layout
1108
1109         layout.operator("curve.select_all", text="All").action = 'SELECT'
1110         layout.operator("curve.select_all", text="None").action = 'DESELECT'
1111         layout.operator("curve.select_all", text="Invert").action = 'INVERT'
1112
1113         layout.separator()
1114
1115         layout.operator("view3d.select_box")
1116         layout.operator("view3d.select_circle")
1117
1118         layout.separator()
1119
1120         layout.operator("curve.select_random")
1121         layout.operator("curve.select_nth")
1122         layout.operator("curve.select_linked", text="Select Linked")
1123         layout.operator("curve.select_similar", text="Select Similar")
1124
1125         layout.separator()
1126
1127         layout.operator("curve.select_row")
1128
1129         layout.separator()
1130
1131         layout.operator("curve.select_more")
1132         layout.operator("curve.select_less")
1133
1134
1135 class VIEW3D_MT_edit_text_context_menu(Menu):
1136     bl_label = "Text Context Menu"
1137
1138     def draw(self, context):
1139         layout = self.layout
1140
1141         layout = self.layout
1142
1143         layout.operator_context = 'INVOKE_DEFAULT'
1144
1145         layout.operator("font.text_cut", text="Cut")
1146         layout.operator("font.text_copy", text="Copy", icon='COPYDOWN')
1147         layout.operator("font.text_paste", text="Paste", icon='PASTEDOWN')
1148
1149         layout.separator()
1150
1151         layout.operator("font.select_all")
1152
1153         layout.separator()
1154
1155         layout.menu("VIEW3D_MT_edit_font")
1156
1157
1158 class VIEW3D_MT_select_edit_text(Menu):
1159     # intentional name mismatch
1160     # select menu for 3d-text doesn't make sense
1161     bl_label = "Edit"
1162
1163     def draw(self, context):
1164         layout = self.layout
1165
1166         layout.operator("font.text_cut", text="Cut")
1167         layout.operator("font.text_copy", text="Copy", icon='COPYDOWN')
1168         layout.operator("font.text_paste", text="Paste", icon='PASTEDOWN')
1169
1170         layout.separator()
1171
1172         layout.operator("font.text_paste_from_file")
1173
1174         layout.separator()
1175
1176         layout.operator("font.select_all")
1177
1178         layout.menu("VIEW3D_MT_edit_font")
1179
1180
1181 class VIEW3D_MT_select_edit_metaball(Menu):
1182     bl_label = "Select"
1183
1184     def draw(self, context):
1185         layout = self.layout
1186
1187         layout.operator("mball.select_all", text="All").action = 'SELECT'
1188         layout.operator("mball.select_all", text="None").action = 'DESELECT'
1189         layout.operator("mball.select_all", text="Invert").action = 'INVERT'
1190
1191         layout.separator()
1192
1193         layout.operator("view3d.select_box")
1194         layout.operator("view3d.select_circle")
1195
1196         layout.separator()
1197
1198         layout.operator("mball.select_random_metaelems")
1199
1200         layout.separator()
1201
1202         layout.operator_menu_enum("mball.select_similar", "type", text="Similar")
1203
1204
1205 class VIEW3D_MT_edit_lattice_context_menu(Menu):
1206     bl_label = "Lattice Context Menu"
1207
1208     def draw(self, context):
1209         layout = self.layout
1210
1211         layout = self.layout
1212
1213         layout.menu("VIEW3D_MT_mirror")
1214         layout.operator_menu_enum("lattice.flip", "axis")
1215         layout.menu("VIEW3D_MT_snap")
1216
1217         layout.separator()
1218
1219         layout.operator("lattice.make_regular")
1220
1221
1222 class VIEW3D_MT_select_edit_lattice(Menu):
1223     bl_label = "Select"
1224
1225     def draw(self, context):
1226         layout = self.layout
1227
1228         layout.operator("lattice.select_all", text="All").action = 'SELECT'
1229         layout.operator("lattice.select_all", text="None").action = 'DESELECT'
1230         layout.operator("lattice.select_all", text="Invert").action = 'INVERT'
1231
1232         layout.separator()
1233
1234         layout.operator("view3d.select_box")
1235         layout.operator("view3d.select_circle")
1236
1237         layout.separator()
1238
1239         layout.operator("lattice.select_mirror")
1240         layout.operator("lattice.select_random")
1241
1242         layout.separator()
1243
1244         layout.operator("lattice.select_more")
1245         layout.operator("lattice.select_less")
1246
1247         layout.separator()
1248
1249         layout.operator("lattice.select_ungrouped", text="Ungrouped Verts")
1250
1251
1252 class VIEW3D_MT_select_edit_armature(Menu):
1253     bl_label = "Select"
1254
1255     def draw(self, context):
1256         layout = self.layout
1257
1258         layout.operator("armature.select_all", text="All").action = 'SELECT'
1259         layout.operator("armature.select_all", text="None").action = 'DESELECT'
1260         layout.operator("armature.select_all", text="Invert").action = 'INVERT'
1261
1262         layout.separator()
1263
1264         layout.operator("view3d.select_box")
1265         layout.operator("view3d.select_circle")
1266
1267         layout.separator()
1268
1269         layout.operator("armature.select_mirror", text="Mirror").extend = False
1270
1271         layout.separator()
1272
1273         layout.operator("armature.select_more", text="More")
1274         layout.operator("armature.select_less", text="Less")
1275
1276         layout.separator()
1277
1278         props = layout.operator("armature.select_hierarchy", text="Parent")
1279         props.extend = False
1280         props.direction = 'PARENT'
1281
1282         props = layout.operator("armature.select_hierarchy", text="Child")
1283         props.extend = False
1284         props.direction = 'CHILD'
1285
1286         layout.separator()
1287
1288         props = layout.operator("armature.select_hierarchy", text="Extend Parent")
1289         props.extend = True
1290         props.direction = 'PARENT'
1291
1292         props = layout.operator("armature.select_hierarchy", text="Extend Child")
1293         props.extend = True
1294         props.direction = 'CHILD'
1295
1296         layout.operator_menu_enum("armature.select_similar", "type", text="Similar")
1297         layout.operator("object.select_pattern", text="Select Pattern...")
1298
1299
1300 class VIEW3D_MT_select_gpencil(Menu):
1301     bl_label = "Select"
1302
1303     def draw(self, context):
1304         layout = self.layout
1305
1306         layout.operator("gpencil.select_all", text="All").action = 'SELECT'
1307         layout.operator("gpencil.select_all", text="None").action = 'DESELECT'
1308         layout.operator("gpencil.select_all", text="Invert").action = 'INVERT'
1309
1310         layout.separator()
1311
1312         layout.operator("gpencil.select_box")
1313         layout.operator("gpencil.select_circle")
1314
1315         layout.separator()
1316
1317         layout.operator("gpencil.select_linked", text="Linked")
1318         layout.operator("gpencil.select_alternate")
1319         layout.operator_menu_enum("gpencil.select_grouped", "type", text="Grouped")
1320
1321         layout.separator()
1322
1323         layout.operator("gpencil.select_first")
1324         layout.operator("gpencil.select_last")
1325
1326         layout.separator()
1327
1328         layout.operator("gpencil.select_more")
1329         layout.operator("gpencil.select_less")
1330
1331
1332 class VIEW3D_MT_select_paint_mask(Menu):
1333     bl_label = "Select"
1334
1335     def draw(self, context):
1336         layout = self.layout
1337
1338         layout.operator("paint.face_select_all", text="All").action = 'SELECT'
1339         layout.operator("paint.face_select_all", text="None").action = 'DESELECT'
1340         layout.operator("paint.face_select_all", text="Invert").action = 'INVERT'
1341
1342         layout.separator()
1343
1344         layout.operator("view3d.select_box")
1345         layout.operator("view3d.select_circle")
1346
1347         layout.separator()
1348
1349         layout.operator("paint.face_select_linked", text="Linked")
1350
1351
1352 class VIEW3D_MT_select_paint_mask_vertex(Menu):
1353     bl_label = "Select"
1354
1355     def draw(self, context):
1356         layout = self.layout
1357
1358         layout.operator("paint.vert_select_all", text="All").action = 'SELECT'
1359         layout.operator("paint.vert_select_all", text="None").action = 'DESELECT'
1360         layout.operator("paint.vert_select_all", text="Invert").action = 'INVERT'
1361
1362         layout.separator()
1363
1364         layout.operator("view3d.select_box")
1365         layout.operator("view3d.select_circle")
1366
1367         layout.separator()
1368
1369         layout.operator("paint.vert_select_ungrouped", text="Ungrouped Verts")
1370
1371
1372 class VIEW3D_MT_angle_control(Menu):
1373     bl_label = "Angle Control"
1374
1375     @classmethod
1376     def poll(cls, context):
1377         settings = UnifiedPaintPanel.paint_settings(context)
1378         if not settings:
1379             return False
1380
1381         brush = settings.brush
1382         tex_slot = brush.texture_slot
1383
1384         return tex_slot.has_texture_angle and tex_slot.has_texture_angle_source
1385
1386     def draw(self, context):
1387         layout = self.layout
1388
1389         settings = UnifiedPaintPanel.paint_settings(context)
1390         brush = settings.brush
1391
1392         sculpt = (context.sculpt_object is not None)
1393
1394         tex_slot = brush.texture_slot
1395
1396         layout.prop(tex_slot, "use_rake", text="Rake")
1397
1398         if brush.brush_capabilities.has_random_texture_angle and tex_slot.has_random_texture_angle:
1399             if sculpt:
1400                 if brush.sculpt_capabilities.has_random_texture_angle:
1401                     layout.prop(tex_slot, "use_random", text="Random")
1402             else:
1403                 layout.prop(tex_slot, "use_random", text="Random")
1404
1405
1406 class VIEW3D_MT_mesh_add(Menu):
1407     bl_idname = "VIEW3D_MT_mesh_add"
1408     bl_label = "Mesh"
1409
1410     def draw(self, context):
1411         layout = self.layout
1412
1413         layout.operator_context = 'INVOKE_REGION_WIN'
1414
1415         layout.operator("mesh.primitive_plane_add", text="Plane", icon='MESH_PLANE')
1416         layout.operator("mesh.primitive_cube_add", text="Cube", icon='MESH_CUBE')
1417         layout.operator("mesh.primitive_circle_add", text="Circle", icon='MESH_CIRCLE')
1418         layout.operator("mesh.primitive_uv_sphere_add", text="UV Sphere", icon='MESH_UVSPHERE')
1419         layout.operator("mesh.primitive_ico_sphere_add", text="Ico Sphere", icon='MESH_ICOSPHERE')
1420         layout.operator("mesh.primitive_cylinder_add", text="Cylinder", icon='MESH_CYLINDER')
1421         layout.operator("mesh.primitive_cone_add", text="Cone", icon='MESH_CONE')
1422         layout.operator("mesh.primitive_torus_add", text="Torus", icon='MESH_TORUS')
1423
1424         layout.separator()
1425
1426         layout.operator("mesh.primitive_grid_add", text="Grid", icon='MESH_GRID')
1427         layout.operator("mesh.primitive_monkey_add", text="Monkey", icon='MESH_MONKEY')
1428
1429
1430 class VIEW3D_MT_curve_add(Menu):
1431     bl_idname = "VIEW3D_MT_curve_add"
1432     bl_label = "Curve"
1433
1434     def draw(self, context):
1435         layout = self.layout
1436
1437         layout.operator_context = 'INVOKE_REGION_WIN'
1438
1439         layout.operator("curve.primitive_bezier_curve_add", text="Bezier", icon='CURVE_BEZCURVE')
1440         layout.operator("curve.primitive_bezier_circle_add", text="Circle", icon='CURVE_BEZCIRCLE')
1441
1442         layout.separator()
1443
1444         layout.operator("curve.primitive_nurbs_curve_add", text="Nurbs Curve", icon='CURVE_NCURVE')
1445         layout.operator("curve.primitive_nurbs_circle_add", text="Nurbs Circle", icon='CURVE_NCIRCLE')
1446         layout.operator("curve.primitive_nurbs_path_add", text="Path", icon='CURVE_PATH')
1447
1448
1449 class VIEW3D_MT_surface_add(Menu):
1450     bl_idname = "VIEW3D_MT_surface_add"
1451     bl_label = "Surface"
1452
1453     def draw(self, context):
1454         layout = self.layout
1455
1456         layout.operator_context = 'INVOKE_REGION_WIN'
1457
1458         layout.operator("surface.primitive_nurbs_surface_curve_add", text="Nurbs Curve", icon='SURFACE_NCURVE')
1459         layout.operator("surface.primitive_nurbs_surface_circle_add", text="Nurbs Circle", icon='SURFACE_NCIRCLE')
1460         layout.operator("surface.primitive_nurbs_surface_surface_add", text="Nurbs Surface", icon='SURFACE_NSURFACE')
1461         layout.operator("surface.primitive_nurbs_surface_cylinder_add",
1462                         text="Nurbs Cylinder", icon='SURFACE_NCYLINDER')
1463         layout.operator("surface.primitive_nurbs_surface_sphere_add", text="Nurbs Sphere", icon='SURFACE_NSPHERE')
1464         layout.operator("surface.primitive_nurbs_surface_torus_add", text="Nurbs Torus", icon='SURFACE_NTORUS')
1465
1466
1467 class VIEW3D_MT_edit_metaball_context_menu(Menu):
1468     bl_label = "Metaball Context Menu"
1469
1470     def draw(self, context):
1471         layout = self.layout
1472
1473         layout.operator_context = 'INVOKE_REGION_WIN'
1474
1475         # Add
1476         layout.operator("mball.duplicate_move")
1477
1478         layout.separator()
1479
1480         # Modify
1481         layout.menu("VIEW3D_MT_mirror")
1482         layout.menu("VIEW3D_MT_snap")
1483
1484         layout.separator()
1485
1486         # Remove
1487         layout.operator_context = 'EXEC_DEFAULT'
1488         layout.operator("mball.delete_metaelems", text="Delete")
1489
1490
1491 class VIEW3D_MT_metaball_add(Menu):
1492     bl_idname = "VIEW3D_MT_metaball_add"
1493     bl_label = "Metaball"
1494
1495     def draw(self, context):
1496         layout = self.layout
1497
1498         layout.operator_context = 'INVOKE_REGION_WIN'
1499         layout.operator_enum("object.metaball_add", "type")
1500
1501
1502 class TOPBAR_MT_edit_curve_add(Menu):
1503     bl_idname = "TOPBAR_MT_edit_curve_add"
1504     bl_label = "Add"
1505
1506     def draw(self, context):
1507         is_surf = context.active_object.type == 'SURFACE'
1508
1509         layout = self.layout
1510         layout.operator_context = 'EXEC_REGION_WIN'
1511
1512         if is_surf:
1513             VIEW3D_MT_surface_add.draw(self, context)
1514         else:
1515             VIEW3D_MT_curve_add.draw(self, context)
1516
1517
1518 class TOPBAR_MT_edit_armature_add(Menu):
1519     bl_idname = "TOPBAR_MT_edit_armature_add"
1520     bl_label = "Armature"
1521
1522     def draw(self, context):
1523         layout = self.layout
1524
1525         layout.operator_context = 'EXEC_REGION_WIN'
1526         layout.operator("armature.bone_primitive_add", text="Single Bone", icon='BONE_DATA')
1527
1528
1529 class VIEW3D_MT_armature_add(Menu):
1530     bl_idname = "VIEW3D_MT_armature_add"
1531     bl_label = "Armature"
1532
1533     def draw(self, context):
1534         layout = self.layout
1535
1536         layout.operator_context = 'EXEC_REGION_WIN'
1537         layout.operator("object.armature_add", text="Single Bone", icon='BONE_DATA')
1538
1539
1540 class VIEW3D_MT_light_add(Menu):
1541     bl_idname = "VIEW3D_MT_light_add"
1542     bl_label = "Light"
1543
1544     def draw(self, context):
1545         layout = self.layout
1546
1547         layout.operator_context = 'INVOKE_REGION_WIN'
1548         layout.operator_enum("object.light_add", "type")
1549
1550
1551 class VIEW3D_MT_lightprobe_add(Menu):
1552     bl_idname = "VIEW3D_MT_lightprobe_add"
1553     bl_label = "Light Probe"
1554
1555     def draw(self, context):
1556         layout = self.layout
1557
1558         layout.operator_context = 'INVOKE_REGION_WIN'
1559         layout.operator_enum("object.lightprobe_add", "type")
1560
1561
1562 class VIEW3D_MT_camera_add(Menu):
1563     bl_idname = "VIEW3D_MT_camera_add"
1564     bl_label = "Camera"
1565
1566     def draw(self, context):
1567         layout = self.layout
1568         layout.operator_context = 'EXEC_REGION_WIN'
1569         layout.operator("object.camera_add", text="Camera", icon='OUTLINER_OB_CAMERA')
1570
1571
1572 class VIEW3D_MT_add(Menu):
1573     bl_label = "Add"
1574
1575     def draw(self, context):
1576         layout = self.layout
1577
1578         # note, don't use 'EXEC_SCREEN' or operators won't get the 'v3d' context.
1579
1580         # Note: was EXEC_AREA, but this context does not have the 'rv3d', which prevents
1581         #       "align_view" to work on first call (see [#32719]).
1582         layout.operator_context = 'EXEC_REGION_WIN'
1583
1584         # layout.operator_menu_enum("object.mesh_add", "type", text="Mesh", icon='OUTLINER_OB_MESH')
1585         layout.menu("VIEW3D_MT_mesh_add", icon='OUTLINER_OB_MESH')
1586
1587         # layout.operator_menu_enum("object.curve_add", "type", text="Curve", icon='OUTLINER_OB_CURVE')
1588         layout.menu("VIEW3D_MT_curve_add", icon='OUTLINER_OB_CURVE')
1589         # layout.operator_menu_enum("object.surface_add", "type", text="Surface", icon='OUTLINER_OB_SURFACE')
1590         layout.menu("VIEW3D_MT_surface_add", icon='OUTLINER_OB_SURFACE')
1591         layout.menu("VIEW3D_MT_metaball_add", text="Metaball", icon='OUTLINER_OB_META')
1592         layout.operator("object.text_add", text="Text", icon='OUTLINER_OB_FONT')
1593         layout.operator_menu_enum("object.gpencil_add", "type", text="Grease Pencil", icon='OUTLINER_OB_GREASEPENCIL')
1594
1595         layout.separator()
1596
1597         if VIEW3D_MT_armature_add.is_extended():
1598             layout.menu("VIEW3D_MT_armature_add", icon='OUTLINER_OB_ARMATURE')
1599         else:
1600             layout.operator("object.armature_add", text="Armature", icon='OUTLINER_OB_ARMATURE')
1601
1602         layout.operator("object.add", text="Lattice", icon='OUTLINER_OB_LATTICE').type = 'LATTICE'
1603
1604         layout.separator()
1605
1606         layout.operator_menu_enum("object.empty_add", "type", text="Empty", icon='OUTLINER_OB_EMPTY')
1607         layout.menu("VIEW3D_MT_image_add", text="Image", icon='OUTLINER_OB_IMAGE')
1608
1609         layout.separator()
1610
1611         layout.menu("VIEW3D_MT_light_add", icon='OUTLINER_OB_LIGHT')
1612         layout.menu("VIEW3D_MT_lightprobe_add", icon='OUTLINER_OB_LIGHTPROBE')
1613
1614         layout.separator()
1615
1616         if VIEW3D_MT_camera_add.is_extended():
1617             layout.menu("VIEW3D_MT_camera_add", icon='OUTLINER_OB_CAMERA')
1618         else:
1619             VIEW3D_MT_camera_add.draw(self, context)
1620
1621         layout.separator()
1622
1623         layout.operator("object.speaker_add", text="Speaker", icon='OUTLINER_OB_SPEAKER')
1624
1625         layout.separator()
1626
1627         layout.operator_menu_enum("object.effector_add", "type", text="Force Field", icon='OUTLINER_OB_FORCE_FIELD')
1628
1629         layout.separator()
1630
1631         has_collections = bool(bpy.data.collections)
1632         col = layout.column()
1633         col.enabled = has_collections
1634
1635         if not has_collections or len(bpy.data.collections) > 10:
1636             col.operator_context = 'INVOKE_REGION_WIN'
1637             col.operator(
1638                 "object.collection_instance_add",
1639                 text="Collection Instance..." if has_collections else "No Collections to Instance",
1640                 icon='OUTLINER_OB_GROUP_INSTANCE',
1641             )
1642         else:
1643             col.operator_menu_enum(
1644                 "object.collection_instance_add",
1645                 "collection",
1646                 text="Collection Instance",
1647                 icon='OUTLINER_OB_GROUP_INSTANCE',
1648             )
1649
1650
1651 class VIEW3D_MT_image_add(Menu):
1652     bl_label = "Add Image"
1653
1654     def draw(self, context):
1655         layout = self.layout
1656         layout.operator("object.load_reference_image", text="Reference", icon='IMAGE_REFERENCE')
1657         layout.operator("object.load_background_image", text="Background", icon='IMAGE_BACKGROUND')
1658
1659
1660 class VIEW3D_MT_object_relations(Menu):
1661     bl_label = "Relations"
1662
1663     def draw(self, context):
1664         layout = self.layout
1665
1666         layout.operator("object.proxy_make", text="Make Proxy...")
1667
1668         layout.operator("object.make_dupli_face")
1669
1670         layout.separator()
1671
1672         layout.operator_menu_enum("object.make_local", "type", text="Make Local...")
1673         layout.menu("VIEW3D_MT_make_single_user")
1674
1675         layout.separator()
1676
1677         layout.operator("object.data_transfer")
1678         layout.operator("object.datalayout_transfer")
1679
1680
1681 class VIEW3D_MT_object(Menu):
1682     bl_context = "objectmode"
1683     bl_label = "Object"
1684
1685     def draw(self, context):
1686         layout = self.layout
1687
1688         layout.menu("VIEW3D_MT_transform_object")
1689         layout.operator_menu_enum("object.origin_set", text="Set Origin", property="type")
1690         layout.menu("VIEW3D_MT_mirror")
1691         layout.menu("VIEW3D_MT_object_clear")
1692         layout.menu("VIEW3D_MT_object_apply")
1693         layout.menu("VIEW3D_MT_snap")
1694
1695         layout.separator()
1696
1697         layout.operator("object.duplicate_move")
1698         layout.operator("object.duplicate_move_linked")
1699         layout.operator("object.join")
1700
1701         layout.separator()
1702
1703         layout.operator("view3d.copybuffer", text="Copy Objects", icon='COPYDOWN')
1704         layout.operator("view3d.pastebuffer", text="Paste Objects", icon='PASTEDOWN')
1705
1706         layout.separator()
1707
1708         layout.menu("VIEW3D_MT_object_parent")
1709         layout.menu("VIEW3D_MT_object_collection")
1710         layout.menu("VIEW3D_MT_object_relations")
1711         layout.menu("VIEW3D_MT_object_constraints")
1712         layout.menu("VIEW3D_MT_object_track")
1713         layout.menu("VIEW3D_MT_make_links", text="Make Links")
1714
1715         layout.separator()
1716
1717         layout.operator("object.shade_smooth")
1718         layout.operator("object.shade_flat")
1719
1720         layout.separator()
1721
1722         layout.menu("VIEW3D_MT_object_animation")
1723         layout.menu("VIEW3D_MT_object_rigid_body")
1724
1725         layout.separator()
1726
1727         layout.menu("VIEW3D_MT_object_quick_effects")
1728
1729         layout.separator()
1730
1731         ob = context.active_object
1732         if ob and ob.type == 'GPENCIL' and context.gpencil_data:
1733             layout.operator_menu_enum("gpencil.convert", "type", text="Convert to")
1734         else:
1735             layout.operator_menu_enum("object.convert", "target")
1736
1737         layout.separator()
1738
1739         layout.menu("VIEW3D_MT_object_showhide")
1740
1741         layout.separator()
1742
1743         layout.operator_context = 'EXEC_DEFAULT'
1744         layout.operator("object.delete", text="Delete").use_global = False
1745         layout.operator("object.delete", text="Delete Global").use_global = True
1746
1747
1748 class VIEW3D_MT_object_animation(Menu):
1749     bl_label = "Animation"
1750
1751     def draw(self, context):
1752         layout = self.layout
1753
1754         layout.operator("anim.keyframe_insert_menu", text="Insert Keyframe...")
1755         layout.operator("anim.keyframe_delete_v3d", text="Delete Keyframes...")
1756         layout.operator("anim.keyframe_clear_v3d", text="Clear Keyframes...")
1757         layout.operator("anim.keying_set_active_set", text="Change Keying Set...")
1758
1759         layout.separator()
1760
1761         layout.operator("nla.bake", text="Bake Action...")
1762
1763
1764 class VIEW3D_MT_object_rigid_body(Menu):
1765     bl_label = "Rigid Body"
1766
1767     def draw(self, context):
1768         layout = self.layout
1769
1770         layout.operator("rigidbody.objects_add", text="Add Active").type = 'ACTIVE'
1771         layout.operator("rigidbody.objects_add", text="Add Passive").type = 'PASSIVE'
1772
1773         layout.separator()
1774
1775         layout.operator("rigidbody.objects_remove", text="Remove")
1776
1777         layout.separator()
1778
1779         layout.operator("rigidbody.shape_change", text="Change Shape")
1780         layout.operator("rigidbody.mass_calculate", text="Calculate Mass")
1781         layout.operator("rigidbody.object_settings_copy", text="Copy from Active")
1782         layout.operator("object.visual_transform_apply", text="Apply Transformation")
1783         layout.operator("rigidbody.bake_to_keyframes", text="Bake To Keyframes")
1784
1785         layout.separator()
1786
1787         layout.operator("rigidbody.connect", text="Connect")
1788
1789
1790 class VIEW3D_MT_object_clear(Menu):
1791     bl_label = "Clear"
1792
1793     def draw(self, context):
1794         layout = self.layout
1795
1796         layout.operator("object.location_clear", text="Location").clear_delta = False
1797         layout.operator("object.rotation_clear", text="Rotation").clear_delta = False
1798         layout.operator("object.scale_clear", text="Scale").clear_delta = False
1799
1800         layout.separator()
1801
1802         layout.operator("object.origin_clear", text="Origin")
1803
1804
1805 class VIEW3D_MT_object_context_menu(Menu):
1806     bl_label = "Object Context Menu"
1807
1808     def draw(self, context):
1809
1810         layout = self.layout
1811         view = context.space_data
1812
1813         obj = context.object
1814         is_eevee = context.scene.render.engine == 'BLENDER_EEVEE'
1815
1816         selected_objects_len = len(context.selected_objects)
1817
1818         # If nothing is selected
1819         # (disabled for now until it can be made more useful).
1820         '''
1821         if selected_objects_len == 0:
1822
1823             layout.menu("VIEW3D_MT_add", text="Add")
1824             layout.operator("view3d.pastebuffer", text="Paste Objects", icon='PASTEDOWN')
1825
1826             return
1827         '''
1828
1829         # If something is selected
1830         if obj is not None and obj.type in {'MESH', 'CURVE', 'SURFACE'}:
1831             layout.operator("object.shade_smooth", text="Shade Smooth")
1832             layout.operator("object.shade_flat", text="Shade Flat")
1833
1834             layout.separator()
1835
1836         if obj is None:
1837             pass
1838         elif obj.type == 'MESH':
1839             layout.operator_context = 'INVOKE_REGION_WIN'
1840             layout.operator_menu_enum("object.origin_set", text="Set Origin", property="type")
1841
1842             layout.operator_context = 'INVOKE_DEFAULT'
1843             # If more than one object is selected
1844             if selected_objects_len > 1:
1845                 layout.operator("object.join")
1846
1847             layout.separator()
1848
1849         elif obj.type == 'CAMERA':
1850             layout.operator_context = 'INVOKE_REGION_WIN'
1851
1852             if obj.data.type == 'PERSP':
1853                 props = layout.operator("wm.context_modal_mouse", text="Camera Lens Angle")
1854                 props.data_path_iter = "selected_editable_objects"
1855                 props.data_path_item = "data.lens"
1856                 props.input_scale = 0.1
1857                 if obj.data.lens_unit == 'MILLIMETERS':
1858                     props.header_text = "Camera Lens Angle: %.1fmm"
1859                 else:
1860                     props.header_text = "Camera Lens Angle: %.1f\u00B0"
1861
1862             else:
1863                 props = layout.operator("wm.context_modal_mouse", text="Camera Lens Scale")
1864                 props.data_path_iter = "selected_editable_objects"
1865                 props.data_path_item = "data.ortho_scale"
1866                 props.input_scale = 0.01
1867                 props.header_text = "Camera Lens Scale: %.3f"
1868
1869             if not obj.data.dof_object:
1870                 if view and view.camera == obj and view.region_3d.view_perspective == 'CAMERA':
1871                     props = layout.operator("ui.eyedropper_depth", text="DOF Distance (Pick)")
1872                 else:
1873                     props = layout.operator("wm.context_modal_mouse", text="DOF Distance")
1874                     props.data_path_iter = "selected_editable_objects"
1875                     props.data_path_item = "data.dof_distance"
1876                     props.input_scale = 0.02
1877                     props.header_text = "DOF Distance: %.3f"
1878
1879             layout.separator()
1880
1881         elif obj.type in {'CURVE', 'FONT'}:
1882             layout.operator_context = 'INVOKE_REGION_WIN'
1883
1884             props = layout.operator("wm.context_modal_mouse", text="Extrude Size")
1885             props.data_path_iter = "selected_editable_objects"
1886             props.data_path_item = "data.extrude"
1887             props.input_scale = 0.01
1888             props.header_text = "Extrude Size: %.3f"
1889
1890             props = layout.operator("wm.context_modal_mouse", text="Width Size")
1891             props.data_path_iter = "selected_editable_objects"
1892             props.data_path_item = "data.offset"
1893             props.input_scale = 0.01
1894             props.header_text = "Width Size: %.3f"
1895
1896             layout.separator()
1897
1898             layout.operator("object.convert", text="Convert to Mesh").target = 'MESH'
1899             layout.operator_menu_enum("object.origin_set", text="Set Origin", property="type")
1900
1901             layout.separator()
1902
1903         elif obj.type == 'GPENCIL':
1904             layout.operator("gpencil.convert", text="Convert to Path").type = 'PATH'
1905             layout.operator("gpencil.convert", text="Convert to Bezier Curves").type = 'CURVE'
1906             layout.operator("gpencil.convert", text="Convert to Mesh").type = 'POLY'
1907
1908             layout.operator_menu_enum("object.origin_set", text="Set Origin", property="type")
1909
1910             layout.separator()
1911
1912         elif obj.type == 'EMPTY':
1913             layout.operator_context = 'INVOKE_REGION_WIN'
1914
1915             props = layout.operator("wm.context_modal_mouse", text="Empty Draw Size")
1916             props.data_path_iter = "selected_editable_objects"
1917             props.data_path_item = "empty_display_size"
1918             props.input_scale = 0.01
1919             props.header_text = "Empty Draw Size: %.3f"
1920
1921             layout.separator()
1922
1923         elif obj.type == 'LIGHT':
1924             light = obj.data
1925
1926             layout.operator_context = 'INVOKE_REGION_WIN'
1927
1928             emission_node = None
1929             if light.node_tree:
1930                 for node in light.node_tree.nodes:
1931                     if getattr(node, "type", None) == 'EMISSION':
1932                         emission_node = node
1933                         break
1934
1935             if is_eevee and not emission_node:
1936                 props = layout.operator("wm.context_modal_mouse", text="Energy")
1937                 props.data_path_iter = "selected_editable_objects"
1938                 props.data_path_item = "data.energy"
1939                 props.header_text = "Light Energy: %.3f"
1940
1941             if emission_node is not None:
1942                 props = layout.operator("wm.context_modal_mouse", text="Energy")
1943                 props.data_path_iter = "selected_editable_objects"
1944                 props.data_path_item = (
1945                     "data.node_tree"
1946                     ".nodes[\"" + emission_node.name + "\"]"
1947                     ".inputs[\"Strength\"].default_value"
1948                 )
1949                 props.header_text = "Light Energy: %.3f"
1950                 props.input_scale = 0.1
1951
1952             if light.type == 'AREA':
1953                 props = layout.operator("wm.context_modal_mouse", text="Size X")
1954                 props.data_path_iter = "selected_editable_objects"
1955                 props.data_path_item = "data.size"
1956                 props.header_text = "Light Size X: %.3f"
1957
1958                 if light.shape in {'RECTANGLE', 'ELLIPSE'}:
1959                     props = layout.operator("wm.context_modal_mouse", text="Size Y")
1960                     props.data_path_iter = "selected_editable_objects"
1961                     props.data_path_item = "data.size_y"
1962                     props.header_text = "Light Size Y: %.3f"
1963
1964             elif light.type in {'SPOT', 'POINT', 'SUN'}:
1965                 props = layout.operator("wm.context_modal_mouse", text="Radius")
1966                 props.data_path_iter = "selected_editable_objects"
1967                 props.data_path_item = "data.shadow_soft_size"
1968                 props.header_text = "Light Radius: %.3f"
1969
1970             if light.type == 'SPOT':
1971                 layout.separator()
1972
1973                 props = layout.operator("wm.context_modal_mouse", text="Spot Size")
1974                 props.data_path_iter = "selected_editable_objects"
1975                 props.data_path_item = "data.spot_size"
1976                 props.input_scale = 0.01
1977                 props.header_text = "Spot Size: %.2f"
1978
1979                 props = layout.operator("wm.context_modal_mouse", text="Spot Blend")
1980                 props.data_path_iter = "selected_editable_objects"
1981                 props.data_path_item = "data.spot_blend"
1982                 props.input_scale = -0.01
1983                 props.header_text = "Spot Blend: %.2f"
1984
1985             layout.separator()
1986
1987         layout.operator("view3d.copybuffer", text="Copy Objects", icon='COPYDOWN')
1988         layout.operator("view3d.pastebuffer", text="Paste Objects", icon='PASTEDOWN')
1989
1990         layout.separator()
1991
1992         layout.operator("object.duplicate_move", icon='DUPLICATE')
1993         layout.operator("object.duplicate_move_linked")
1994
1995         layout.separator()
1996
1997         props = layout.operator("wm.call_panel", text="Rename Active Object...")
1998         props.name = "TOPBAR_PT_name"
1999         props.keep_open = False
2000
2001         layout.separator()
2002
2003         layout.menu("VIEW3D_MT_mirror")
2004         layout.menu("VIEW3D_MT_snap")
2005         layout.menu("VIEW3D_MT_object_parent")
2006         layout.operator_context = 'INVOKE_REGION_WIN'
2007
2008         if view and view.local_view:
2009             layout.operator("view3d.localview_remove_from")
2010         else:
2011             layout.operator("object.move_to_collection")
2012
2013         layout.separator()
2014
2015         layout.operator("anim.keyframe_insert_menu", text="Insert Keyframe...")
2016
2017         layout.separator()
2018
2019         layout.operator_context = 'EXEC_DEFAULT'
2020         layout.operator("object.delete", text="Delete").use_global = False
2021
2022
2023 class VIEW3D_MT_object_shading(Menu):
2024     # XXX, this menu is a place to store shading operator in object mode
2025     bl_label = "Shading"
2026
2027     def draw(self, context):
2028         layout = self.layout
2029         layout.operator("object.shade_smooth", text="Smooth")
2030         layout.operator("object.shade_flat", text="Flat")
2031
2032
2033 class VIEW3D_MT_object_apply(Menu):
2034     bl_label = "Apply"
2035
2036     def draw(self, context):
2037         layout = self.layout
2038
2039         props = layout.operator("object.transform_apply", text="Location", text_ctxt=i18n_contexts.default)
2040         props.location, props.rotation, props.scale = True, False, False
2041
2042         props = layout.operator("object.transform_apply", text="Rotation", text_ctxt=i18n_contexts.default)
2043         props.location, props.rotation, props.scale = False, True, False
2044
2045         props = layout.operator("object.transform_apply", text="Scale", text_ctxt=i18n_contexts.default)
2046         props.location, props.rotation, props.scale = False, False, True
2047
2048         props = layout.operator("object.transform_apply", text="All Transforms", text_ctxt=i18n_contexts.default)
2049         props.location, props.rotation, props.scale = True, True, True
2050
2051         props = layout.operator("object.transform_apply", text="Rotation & Scale", text_ctxt=i18n_contexts.default)
2052         props.location, props.rotation, props.scale = False, True, True
2053
2054         layout.separator()
2055
2056         layout.operator(
2057             "object.transforms_to_deltas",
2058             text="Location to Deltas",
2059             text_ctxt=i18n_contexts.default,
2060         ).mode = 'LOC'
2061         layout.operator(
2062             "object.transforms_to_deltas",
2063             text="Rotation to Deltas",
2064             text_ctxt=i18n_contexts.default,
2065         ).mode = 'ROT'
2066         layout.operator(
2067             "object.transforms_to_deltas",
2068             text="Scale to Deltas",
2069             text_ctxt=i18n_contexts.default,
2070         ).mode = 'SCALE'
2071
2072         layout.operator(
2073             "object.transforms_to_deltas",
2074             text="All Transforms to Deltas",
2075             text_ctxt=i18n_contexts.default,
2076         ).mode = 'ALL'
2077         layout.operator("object.anim_transforms_to_deltas")
2078
2079         layout.separator()
2080
2081         layout.operator(
2082             "object.visual_transform_apply",
2083             text="Visual Transform",
2084             text_ctxt=i18n_contexts.default,
2085         )
2086         layout.operator(
2087             "object.convert",
2088             text="Visual Geometry to Mesh",
2089             text_ctxt=i18n_contexts.default,
2090         ).target = 'MESH'
2091         layout.operator("object.duplicates_make_real")
2092
2093
2094 class VIEW3D_MT_object_parent(Menu):
2095     bl_label = "Parent"
2096
2097     def draw(self, context):
2098         layout = self.layout
2099
2100         layout.operator_enum("object.parent_set", "type")
2101
2102         layout.separator()
2103
2104         layout.operator_enum("object.parent_clear", "type")
2105
2106
2107 class VIEW3D_MT_object_track(Menu):
2108     bl_label = "Track"
2109
2110     def draw(self, context):
2111         layout = self.layout
2112
2113         layout.operator_enum("object.track_set", "type")
2114
2115         layout.separator()
2116
2117         layout.operator_enum("object.track_clear", "type")
2118
2119
2120 class VIEW3D_MT_object_collection(Menu):
2121     bl_label = "Collection"
2122
2123     def draw(self, context):
2124         layout = self.layout
2125
2126         layout.operator("object.move_to_collection")
2127         layout.operator("object.link_to_collection")
2128
2129         layout.separator()
2130
2131         layout.operator("collection.create")
2132         # layout.operator_menu_enum("collection.objects_remove", "collection")  # BUGGY
2133         layout.operator("collection.objects_remove")
2134         layout.operator("collection.objects_remove_all")
2135
2136         layout.separator()
2137
2138         layout.operator("collection.objects_add_active")
2139         layout.operator("collection.objects_remove_active")
2140
2141
2142 class VIEW3D_MT_object_constraints(Menu):
2143     bl_label = "Constraints"
2144
2145     def draw(self, context):
2146         layout = self.layout
2147
2148         layout.operator("object.constraint_add_with_targets")
2149         layout.operator("object.constraints_copy")
2150
2151         layout.separator()
2152
2153         layout.operator("object.constraints_clear")
2154
2155
2156 class VIEW3D_MT_object_quick_effects(Menu):
2157     bl_label = "Quick Effects"
2158
2159     def draw(self, context):
2160         layout = self.layout
2161
2162         layout.operator("object.quick_fur")
2163         layout.operator("object.quick_explode")
2164         layout.operator("object.quick_smoke")
2165         layout.operator("object.quick_fluid")
2166
2167
2168 class VIEW3D_MT_object_showhide(Menu):
2169     bl_label = "Show/Hide"
2170
2171     def draw(self, context):
2172         layout = self.layout
2173
2174         layout.operator("object.hide_view_clear")
2175
2176         layout.separator()
2177
2178         layout.operator("object.hide_view_set", text="Hide Selected").unselected = False
2179         layout.operator("object.hide_view_set", text="Hide Unselected").unselected = True
2180
2181
2182 class VIEW3D_MT_make_single_user(Menu):
2183     bl_label = "Make Single User"
2184
2185     def draw(self, context):
2186         layout = self.layout
2187
2188         props = layout.operator("object.make_single_user", text="Object")
2189         props.object = True
2190         props.obdata = props.material = props.animation = False
2191
2192         props = layout.operator("object.make_single_user", text="Object & Data")
2193         props.object = props.obdata = True
2194         props.material = props.animation = False
2195
2196         props = layout.operator("object.make_single_user", text="Object & Data & Materials")
2197         props.object = props.obdata = props.material = True
2198         props.animation = False
2199
2200         props = layout.operator("object.make_single_user", text="Materials")
2201         props.material = True
2202         props.object = props.obdata = props.animation = False
2203
2204         props = layout.operator("object.make_single_user", text="Object Animation")
2205         props.animation = True
2206         props.object = props.obdata = props.material = False
2207
2208
2209 class VIEW3D_MT_make_links(Menu):
2210     bl_label = "Make Links"
2211
2212     def draw(self, context):
2213         layout = self.layout
2214         operator_context_default = layout.operator_context
2215
2216         if len(bpy.data.scenes) > 10:
2217             layout.operator_context = 'INVOKE_REGION_WIN'
2218             layout.operator("object.make_links_scene", text="Objects to Scene...", icon='OUTLINER_OB_EMPTY')
2219         else:
2220             layout.operator_context = 'EXEC_REGION_WIN'
2221             layout.operator_menu_enum("object.make_links_scene", "scene", text="Objects to Scene")
2222
2223         layout.separator()
2224
2225         layout.operator_context = operator_context_default
2226
2227         layout.operator_enum("object.make_links_data", "type")  # inline
2228
2229         layout.operator("object.join_uvs")  # stupid place to add this!
2230
2231
2232 class VIEW3D_MT_brush(Menu):
2233     bl_label = "Brush"
2234
2235     def draw(self, context):
2236         layout = self.layout
2237
2238         tool_settings = context.tool_settings
2239         settings = UnifiedPaintPanel.paint_settings(context)
2240         brush = getattr(settings, "brush", None)
2241
2242         ups = tool_settings.unified_paint_settings
2243         layout.prop(ups, "use_unified_size", text="Unified Size")
2244         layout.prop(ups, "use_unified_strength", text="Unified Strength")
2245         if context.image_paint_object or context.vertex_paint_object:
2246             layout.prop(ups, "use_unified_color", text="Unified Color")
2247         layout.separator()
2248
2249         # skip if no active brush
2250         if not brush:
2251             layout.label(text="No Brushes currently available", icon='INFO')
2252             return
2253
2254         # brush paint modes
2255         layout.menu("VIEW3D_MT_brush_paint_modes")
2256
2257         # brush tool
2258         if context.sculpt_object:
2259             layout.operator("brush.reset")
2260             layout.prop_menu_enum(brush, "sculpt_tool")
2261         elif context.image_paint_object:
2262             layout.prop_menu_enum(brush, "image_tool")
2263         elif context.vertex_paint_object:
2264             layout.prop_menu_enum(brush, "vertex_tool")
2265         elif context.weight_paint_object:
2266             layout.prop_menu_enum(brush, "weight_tool")
2267
2268         # TODO: still missing a lot of brush options here
2269
2270         # sculpt options
2271         if context.sculpt_object:
2272
2273             sculpt_tool = brush.sculpt_tool
2274
2275             layout.separator()
2276             layout.operator_menu_enum("brush.curve_preset", "shape", text="Curve Preset")
2277             layout.separator()
2278
2279             if sculpt_tool != 'GRAB':
2280                 layout.prop_menu_enum(brush, "stroke_method")
2281
2282                 if sculpt_tool in {'DRAW', 'PINCH', 'INFLATE', 'LAYER', 'CLAY'}:
2283                     layout.prop_menu_enum(brush, "direction")
2284
2285                 if sculpt_tool == 'LAYER':
2286                     layout.prop(brush, "use_persistent")
2287                     layout.operator("sculpt.set_persistent_base")
2288
2289
2290 class VIEW3D_MT_brush_paint_modes(Menu):
2291     bl_label = "Enabled Modes"
2292
2293     def draw(self, context):
2294         layout = self.layout
2295
2296         settings = UnifiedPaintPanel.paint_settings(context)
2297         brush = settings.brush
2298
2299         layout.prop(brush, "use_paint_sculpt", text="Sculpt")
2300         layout.prop(brush, "use_paint_vertex", text="Vertex Paint")
2301         layout.prop(brush, "use_paint_weight", text="Weight Paint")
2302         layout.prop(brush, "use_paint_image", text="Texture Paint")
2303
2304
2305 class VIEW3D_MT_paint_vertex(Menu):
2306     bl_label = "Paint"
2307
2308     def draw(self, context):
2309         layout = self.layout
2310
2311         layout.operator("paint.vertex_color_set")
2312         layout.operator("paint.vertex_color_smooth")
2313         layout.operator("paint.vertex_color_dirt")
2314         layout.operator("paint.vertex_color_from_weight")
2315
2316         layout.separator()
2317
2318         layout.operator("paint.vertex_color_invert", text="Invert")
2319         layout.operator("paint.vertex_color_levels", text="Levels")
2320         layout.operator("paint.vertex_color_hsv", text="Hue Saturation Value")
2321         layout.operator("paint.vertex_color_brightness_contrast", text="Bright/Contrast")
2322
2323
2324 class VIEW3D_MT_hook(Menu):
2325     bl_label = "Hooks"
2326
2327     def draw(self, context):
2328         layout = self.layout
2329         layout.operator_context = 'EXEC_AREA'
2330         layout.operator("object.hook_add_newob")
2331         layout.operator("object.hook_add_selob").use_bone = False
2332         layout.operator("object.hook_add_selob", text="Hook to Selected Object Bone").use_bone = True
2333
2334         if [mod.type == 'HOOK' for mod in context.active_object.modifiers]:
2335             layout.separator()
2336
2337             layout.operator_menu_enum("object.hook_assign", "modifier")
2338             layout.operator_menu_enum("object.hook_remove", "modifier")
2339
2340             layout.separator()
2341
2342             layout.operator_menu_enum("object.hook_select", "modifier")
2343             layout.operator_menu_enum("object.hook_reset", "modifier")
2344             layout.operator_menu_enum("object.hook_recenter", "modifier")
2345
2346
2347 class VIEW3D_MT_vertex_group(Menu):
2348     bl_label = "Vertex Groups"
2349
2350     def draw(self, context):
2351         layout = self.layout
2352
2353         layout.operator_context = 'EXEC_AREA'
2354         layout.operator("object.vertex_group_assign_new")
2355
2356         ob = context.active_object
2357         if ob.mode == 'EDIT' or (ob.mode == 'WEIGHT_PAINT' and ob.type == 'MESH' and ob.data.use_paint_mask_vertex):
2358             if ob.vertex_groups.active:
2359                 layout.separator()
2360
2361                 layout.operator("object.vertex_group_assign", text="Assign to Active Group")
2362                 layout.operator(
2363                     "object.vertex_group_remove_from",
2364                     text="Remove from Active Group",
2365                 ).use_all_groups = False
2366                 layout.operator("object.vertex_group_remove_from", text="Remove from All").use_all_groups = True
2367
2368         if ob.vertex_groups.active:
2369             layout.separator()
2370
2371             layout.operator_menu_enum("object.vertex_group_set_active", "group", text="Set Active Group")
2372             layout.operator("object.vertex_group_remove", text="Remove Active Group").all = False
2373             layout.operator("object.vertex_group_remove", text="Remove All Groups").all = True
2374
2375
2376 class VIEW3D_MT_paint_weight(Menu):
2377     bl_label = "Weights"
2378
2379     @staticmethod
2380     def draw_generic(layout, is_editmode=False):
2381
2382         if not is_editmode:
2383
2384             layout.operator("paint.weight_from_bones", text="Assign Automatic From Bones").type = 'AUTOMATIC'
2385             layout.operator("paint.weight_from_bones", text="Assign From Bone Envelopes").type = 'ENVELOPES'
2386
2387             layout.separator()
2388
2389         layout.operator("object.vertex_group_normalize_all", text="Normalize All")
2390         layout.operator("object.vertex_group_normalize", text="Normalize")
2391
2392         layout.separator()
2393
2394         layout.operator("object.vertex_group_mirror", text="Mirror")
2395         layout.operator("object.vertex_group_invert", text="Invert")
2396         layout.operator("object.vertex_group_clean", text="Clean")
2397
2398         layout.separator()
2399
2400         layout.operator("object.vertex_group_quantize", text="Quantize")
2401         layout.operator("object.vertex_group_levels", text="Levels")
2402         layout.operator("object.vertex_group_smooth", text="Smooth")
2403
2404         if not is_editmode:
2405             props = layout.operator("object.data_transfer", text="Transfer Weights")
2406             props.use_reverse_transfer = True
2407             props.data_type = 'VGROUP_WEIGHTS'
2408
2409         layout.operator("object.vertex_group_limit_total", text="Limit Total")
2410         layout.operator("object.vertex_group_fix", text="Fix Deforms")
2411
2412         if not is_editmode:
2413             layout.separator()
2414
2415             layout.operator("paint.weight_set")
2416
2417     def draw(self, context):
2418         self.draw_generic(self.layout, is_editmode=False)
2419
2420
2421 class VIEW3D_MT_sculpt(Menu):
2422     bl_label = "Sculpt"
2423
2424     def draw(self, context):
2425         layout = self.layout
2426
2427         tool_settings = context.tool_settings
2428         sculpt = tool_settings.sculpt
2429
2430         layout.operator("sculpt.dynamic_topology_toggle", text="Toggle Dynamic Topology")
2431
2432         layout.separator()
2433
2434         layout.prop(sculpt, "use_symmetry_x")
2435         layout.prop(sculpt, "use_symmetry_y")
2436         layout.prop(sculpt, "use_symmetry_z")
2437
2438         layout.separator()
2439
2440         layout.prop(sculpt, "lock_x")
2441         layout.prop(sculpt, "lock_y")
2442         layout.prop(sculpt, "lock_z")
2443
2444         layout.separator()
2445
2446         layout.prop(sculpt, "use_threaded", text="Threaded Sculpt")
2447         layout.prop(sculpt, "show_low_resolution")
2448         layout.prop(sculpt, "show_brush")
2449         layout.prop(sculpt, "use_deform_only")
2450         layout.prop(sculpt, "show_diffuse_color")
2451         layout.prop(sculpt, "show_mask")
2452
2453
2454 class VIEW3D_MT_hide_mask(Menu):
2455     bl_label = "Hide/Mask"
2456
2457     def draw(self, context):
2458         layout = self.layout
2459
2460         props = layout.operator("paint.hide_show", text="Show All")
2461         props.action = 'SHOW'
2462         props.area = 'ALL'
2463
2464         props = layout.operator("paint.hide_show", text="Hide Bounding Box")
2465         props.action = 'HIDE'
2466         props.area = 'INSIDE'
2467
2468         props = layout.operator("paint.hide_show", text="Show Bounding Box")
2469         props.action = 'SHOW'
2470         props.area = 'INSIDE'
2471
2472         props = layout.operator("paint.hide_show", text="Hide Masked")
2473         props.area = 'MASKED'
2474         props.action = 'HIDE'
2475
2476         layout.separator()
2477
2478         props = layout.operator("paint.mask_flood_fill", text="Invert Mask")
2479         props.mode = 'INVERT'
2480
2481         props = layout.operator("paint.mask_flood_fill", text="Fill Mask")
2482         props.mode = 'VALUE'
2483         props.value = 1
2484
2485         props = layout.operator("paint.mask_flood_fill", text="Clear Mask")
2486         props.mode = 'VALUE'
2487         props.value = 0
2488
2489         props = layout.operator("view3d.select_box", text="Box Mask")
2490         props = layout.operator("paint.mask_lasso_gesture", text="Lasso Mask")
2491
2492
2493 class VIEW3D_MT_particle(Menu):
2494     bl_label = "Particle"
2495
2496     def draw(self, context):
2497         layout = self.layout
2498         tool_settings = context.tool_settings
2499
2500         particle_edit = tool_settings.particle_edit
2501
2502         layout.operator("particle.mirror")
2503
2504         layout.operator("particle.remove_doubles")
2505
2506         layout.separator()
2507
2508         if particle_edit.select_mode == 'POINT':
2509             layout.operator("particle.subdivide")
2510
2511         layout.operator("particle.unify_length")
2512         layout.operator("particle.rekey")
2513         layout.operator("particle.weight_set")
2514
2515         layout.separator()
2516
2517         layout.menu("VIEW3D_MT_particle_showhide")
2518
2519         layout.separator()
2520
2521         layout.operator("particle.delete")
2522
2523
2524 class VIEW3D_MT_particle_context_menu(Menu):
2525     bl_label = "Particle Context Menu"
2526
2527     def draw(self, context):
2528         layout = self.layout
2529         tool_settings = context.tool_settings
2530
2531         particle_edit = tool_settings.particle_edit
2532
2533         layout.operator("particle.rekey")
2534
2535         layout.separator()
2536
2537         layout.operator("particle.delete")
2538
2539         layout.separator()
2540
2541         layout.operator("particle.remove_doubles")
2542         layout.operator("particle.unify_length")
2543
2544         if particle_edit.select_mode == 'POINT':
2545             layout.operator("particle.subdivide")
2546
2547         layout.operator("particle.weight_set")
2548
2549         layout.separator()
2550
2551         layout.operator("particle.mirror")
2552
2553         if particle_edit.select_mode == 'POINT':
2554             layout.separator()
2555
2556             layout.operator("particle.select_all", text="All").action = 'SELECT'
2557             layout.operator("particle.select_all", text="None").action = 'DESELECT'
2558             layout.operator("particle.select_all", text="Invert").action = 'INVERT'
2559
2560             layout.separator()
2561
2562             layout.operator("particle.select_roots")
2563             layout.operator("particle.select_tips")
2564
2565             layout.separator()
2566
2567             layout.operator("particle.select_random")
2568
2569             layout.separator()
2570
2571             layout.operator("particle.select_more")
2572             layout.operator("particle.select_less")
2573
2574             layout.separator()
2575
2576             layout.operator("particle.select_linked")
2577
2578
2579 class VIEW3D_MT_particle_showhide(ShowHideMenu, Menu):
2580     _operator_name = "particle"
2581
2582
2583 class VIEW3D_MT_pose(Menu):
2584     bl_label = "Pose"
2585
2586     def draw(self, context):
2587         layout = self.layout
2588
2589         layout.menu("VIEW3D_MT_transform_armature")
2590
2591         layout.menu("VIEW3D_MT_pose_transform")
2592         layout.menu("VIEW3D_MT_pose_apply")
2593
2594         layout.menu("VIEW3D_MT_snap")
2595
2596         layout.separator()
2597
2598         layout.menu("VIEW3D_MT_object_animation")
2599
2600         layout.separator()
2601
2602         layout.menu("VIEW3D_MT_pose_slide")
2603         layout.menu("VIEW3D_MT_pose_propagate")
2604
2605         layout.separator()
2606
2607         layout.operator("pose.copy", icon='COPYDOWN')
2608         layout.operator("pose.paste", icon='PASTEDOWN').flipped = False
2609         layout.operator("pose.paste", icon='PASTEFLIPDOWN', text="Paste Pose Flipped").flipped = True
2610
2611         layout.separator()
2612
2613         layout.menu("VIEW3D_MT_pose_library")
2614         layout.menu("VIEW3D_MT_pose_motion")
2615         layout.menu("VIEW3D_MT_pose_group")
2616
2617         layout.separator()
2618
2619         layout.menu("VIEW3D_MT_object_parent")
2620         layout.menu("VIEW3D_MT_pose_ik")
2621         layout.menu("VIEW3D_MT_pose_constraints")
2622
2623         layout.separator()
2624
2625         layout.operator_context = 'EXEC_AREA'
2626         layout.operator("pose.autoside_names", text="AutoName Left/Right").axis = 'XAXIS'
2627         layout.operator("pose.autoside_names", text="AutoName Front/Back").axis = 'YAXIS'
2628         layout.operator("pose.autoside_names", text="AutoName Top/Bottom").axis = 'ZAXIS'
2629
2630         layout.operator("pose.flip_names")
2631
2632         layout.operator("pose.quaternions_flip")
2633
2634         layout.separator()
2635
2636         layout.operator_context = 'INVOKE_AREA'
2637         layout.operator("armature.armature_layers", text="Change Armature Layers...")
2638         layout.operator("pose.bone_layers", text="Change Bone Layers...")
2639
2640         layout.separator()
2641
2642         layout.menu("VIEW3D_MT_pose_showhide")
2643         layout.menu("VIEW3D_MT_bone_options_toggle", text="Bone Settings")
2644
2645
2646 class VIEW3D_MT_pose_transform(Menu):
2647     bl_label = "Clear Transform"
2648
2649     def draw(self, context):
2650         layout = self.layout
2651
2652         layout.operator("pose.transforms_clear", text="All")
2653
2654         layout.separator()
2655
2656         layout.operator("pose.loc_clear", text="Location")
2657         layout.operator("pose.rot_clear", text="Rotation")
2658         layout.operator("pose.scale_clear", text="Scale")
2659
2660         layout.separator()
2661
2662         layout.operator("pose.user_transforms_clear", text="Reset Unkeyed")
2663
2664
2665 class VIEW3D_MT_pose_slide(Menu):
2666     bl_label = "In-Betweens"
2667
2668     def draw(self, context):
2669         layout = self.layout
2670
2671         layout.operator("pose.push")
2672         layout.operator("pose.relax")
2673         layout.operator("pose.breakdown")
2674
2675
2676 class VIEW3D_MT_pose_propagate(Menu):
2677     bl_label = "Propagate"
2678
2679     def draw(self, context):
2680         layout = self.layout
2681
2682         layout.operator("pose.propagate").mode = 'WHILE_HELD'
2683
2684         layout.separator()
2685
2686         layout.operator("pose.propagate", text="To Next Keyframe").mode = 'NEXT_KEY'
2687         layout.operator("pose.propagate", text="To Last Keyframe (Make Cyclic)").mode = 'LAST_KEY'
2688
2689         layout.separator()
2690
2691         layout.operator("pose.propagate", text="On Selected Keyframes").mode = 'SELECTED_KEYS'
2692
2693         layout.separator()
2694
2695         layout.operator("pose.propagate", text="On Selected Markers").mode = 'SELECTED_MARKERS'
2696
2697
2698 class VIEW3D_MT_pose_library(Menu):
2699     bl_label = "Pose Library"
2700
2701     def draw(self, context):
2702         layout = self.layout
2703
2704         layout.operator("poselib.browse_interactive", text="Browse Poses...")
2705
2706         layout.separator()
2707
2708         layout.operator("poselib.pose_add", text="Add Pose...")
2709         layout.operator("poselib.pose_rename", text="Rename Pose...")
2710         layout.operator("poselib.pose_remove", text="Remove Pose...")
2711
2712
2713 class VIEW3D_MT_pose_motion(Menu):
2714     bl_label = "Motion Paths"
2715
2716     def draw(self, context):
2717         layout = self.layout
2718
2719         layout.operator("pose.paths_calculate", text="Calculate")
2720         layout.operator("pose.paths_clear", text="Clear")
2721
2722
2723 class VIEW3D_MT_pose_group(Menu):
2724     bl_label = "Bone Groups"
2725
2726     def draw(self, context):
2727         layout = self.layout
2728
2729         pose = context.active_object.pose
2730
2731         layout.operator_context = 'EXEC_AREA'
2732         layout.operator("pose.group_assign", text="Assign to New Group").type = 0
2733
2734         if pose.bone_groups:
2735             active_group = pose.bone_groups.active_index + 1
2736             layout.operator("pose.group_assign", text="Assign to Group").type = active_group
2737
2738             layout.separator()
2739
2740             # layout.operator_context = 'INVOKE_AREA'
2741             layout.operator("pose.group_unassign")
2742             layout.operator("pose.group_remove")
2743
2744
2745 class VIEW3D_MT_pose_ik(Menu):
2746     bl_label = "Inverse Kinematics"
2747
2748     def draw(self, context):
2749         layout = self.layout
2750
2751         layout.operator("pose.ik_add")
2752         layout.operator("pose.ik_clear")
2753
2754
2755 class VIEW3D_MT_pose_constraints(Menu):
2756     bl_label = "Constraints"
2757
2758     def draw(self, context):
2759         layout = self.layout
2760
2761         layout.operator("pose.constraint_add_with_targets", text="Add (With Targets)...")
2762         layout.operator("pose.constraints_copy")
2763         layout.operator("pose.constraints_clear")
2764
2765
2766 class VIEW3D_MT_pose_showhide(ShowHideMenu, Menu):
2767     _operator_name = "pose"
2768
2769
2770 class VIEW3D_MT_pose_apply(Menu):
2771     bl_label = "Apply"
2772
2773     def draw(self, context):
2774         layout = self.layout
2775
2776         layout.operator("pose.armature_apply")
2777         layout.operator("pose.visual_transform_apply")
2778
2779         layout.separator()
2780
2781         props = layout.operator("object.assign_property_defaults")
2782         props.process_bones = True
2783
2784
2785 class VIEW3D_MT_pose_context_menu(Menu):
2786     bl_label = "Pose Context Menu"
2787
2788     def draw(self, context):
2789         layout = self.layout
2790
2791         layout.operator_context = 'INVOKE_REGION_WIN'
2792
2793         layout.operator("anim.keyframe_insert_menu", text="Insert Keyframe...")
2794
2795         layout.separator()
2796
2797         layout.operator("pose.copy", icon='COPYDOWN')
2798         layout.operator("pose.paste", icon='PASTEDOWN').flipped = False
2799         layout.operator("pose.paste", icon='PASTEFLIPDOWN', text="Paste X-Flipped Pose").flipped = True
2800
2801         layout.separator()
2802
2803         props = layout.operator("wm.call_panel", text="Rename Active Bone...")
2804         props.name = "TOPBAR_PT_name"
2805         props.keep_open = False
2806
2807         layout.separator()
2808
2809         layout.operator("pose.paths_calculate", text="Calculate")
2810         layout.operator("pose.paths_clear", text="Clear")
2811
2812         layout.separator()
2813
2814         layout.operator("pose.push")
2815         layout.operator("pose.relax")
2816         layout.operator("pose.breakdown")
2817
2818         layout.separator()
2819
2820         layout.operator("pose.paths_calculate", text="Calculate Motion Paths")
2821         layout.operator("pose.paths_clear", text="Clear Motion Paths")
2822
2823         layout.separator()
2824
2825         layout.operator("pose.hide").unselected = False
2826         layout.operator("pose.reveal")
2827
2828         layout.separator()
2829
2830         layout.operator("pose.user_transforms_clear")
2831
2832
2833 class BoneOptions:
2834     def draw(self, context):
2835         layout = self.layout
2836
2837         options = [
2838             "show_wire",
2839             "use_deform",
2840             "use_envelope_multiply",
2841             "use_inherit_rotation",
2842             "use_inherit_scale",
2843         ]
2844
2845         if context.mode == 'EDIT_ARMATURE':
2846             bone_props = bpy.types.EditBone.bl_rna.properties
2847             data_path_iter = "selected_bones"
2848             opt_suffix = ""
2849             options.append("lock")
2850         else:  # pose-mode
2851             bone_props = bpy.types.Bone.bl_rna.properties
2852             data_path_iter = "selected_pose_bones"
2853             opt_suffix = "bone."
2854
2855         for opt in options:
2856             props = layout.operator("wm.context_collection_boolean_set", text=bone_props[opt].name,
2857                                     text_ctxt=i18n_contexts.default)
2858             props.data_path_iter = data_path_iter
2859             props.data_path_item = opt_suffix + opt
2860             props.type = self.type
2861
2862
2863 class VIEW3D_MT_bone_options_toggle(Menu, BoneOptions):
2864     bl_label = "Toggle Bone Options"
2865     type = 'TOGGLE'
2866
2867
2868 class VIEW3D_MT_bone_options_enable(Menu, BoneOptions):
2869     bl_label = "Enable Bone Options"
2870     type = 'ENABLE'
2871
2872
2873 class VIEW3D_MT_bone_options_disable(Menu, BoneOptions):
2874     bl_label = "Disable Bone Options"
2875     type = 'DISABLE'
2876
2877
2878 # ********** Edit Menus, suffix from ob.type **********
2879
2880
2881 class VIEW3D_MT_edit_mesh(Menu):
2882     bl_label = "Mesh"
2883
2884     def draw(self, context):
2885         layout = self.layout
2886
2887         with_bullet = bpy.app.build_options.bullet
2888
2889         layout.menu("VIEW3D_MT_transform")
2890         layout.menu("VIEW3D_MT_mirror")
2891         layout.menu("VIEW3D_MT_snap")
2892
2893         layout.separator()
2894
2895         layout.operator("mesh.duplicate_move", text="Duplicate")
2896         layout.menu("VIEW3D_MT_edit_mesh_extrude")
2897         layout.operator("mesh.split")
2898         layout.operator("mesh.bisect")
2899         layout.operator("mesh.knife_project")
2900
2901         if with_bullet:
2902             layout.operator("mesh.convex_hull")
2903
2904         layout.separator()
2905
2906         layout.operator("mesh.symmetrize")
2907         layout.operator("mesh.symmetry_snap")
2908
2909         layout.separator()
2910
2911         layout.menu("VIEW3D_MT_edit_mesh_normals")
2912         layout.menu("VIEW3D_MT_edit_mesh_shading")
2913         layout.menu("VIEW3D_MT_edit_mesh_weights")
2914         layout.operator_menu_enum("mesh.sort_elements", "type", text="Sort Elements...")
2915
2916         layout.separator()
2917
2918         layout.menu("VIEW3D_MT_edit_mesh_showhide")
2919         layout.operator_menu_enum("mesh.separate", "type")
2920         layout.menu("VIEW3D_MT_edit_mesh_clean")
2921
2922         layout.separator()
2923
2924         layout.menu("VIEW3D_MT_edit_mesh_delete")
2925
2926
2927 class VIEW3D_MT_edit_mesh_context_menu(Menu):
2928     bl_label = ""
2929
2930     def draw(self, context):
2931
2932         def count_selected_items_for_objects_in_mode():
2933             selected_verts_len = 0
2934             selected_edges_len = 0
2935             selected_faces_len = 0
2936             for ob in context.objects_in_mode_unique_data:
2937                 v, e, f = ob.data.count_selected_items()
2938                 selected_verts_len += v
2939                 selected_edges_len += e
2940                 selected_faces_len += f
2941             return (selected_verts_len, selected_edges_len, selected_faces_len)
2942
2943         is_vert_mode, is_edge_mode, is_face_mode = context.tool_settings.mesh_select_mode
2944         selected_verts_len, selected_edges_len, selected_faces_len = count_selected_items_for_objects_in_mode()
2945
2946         del count_selected_items_for_objects_in_mode
2947
2948         layout = self.layout
2949
2950         layout.operator_context = 'INVOKE_REGION_WIN'
2951
2952         # If nothing is selected
2953         # (disabled for now until it can be made more useful).
2954         '''
2955         # If nothing is selected
2956         if not (selected_verts_len or selected_edges_len or selected_faces_len):
2957             layout.menu("VIEW3D_MT_mesh_add", text="Add")
2958
2959             return
2960         '''
2961
2962         # Else something is selected
2963
2964         row = layout.row()
2965
2966         if is_vert_mode:
2967             col = row.column()
2968
2969             col.label(text="Vertex Context Menu", icon='VERTEXSEL')
2970             col.separator()
2971
2972             # Additive Operators
2973             col.operator("mesh.subdivide", text="Subdivide")
2974
2975             col.separator()
2976
2977             col.operator("mesh.extrude_vertices_move", text="Extrude Vertices"),
2978             col.operator("mesh.bevel", text="Bevel Vertices").vertex_only = True
2979
2980             if selected_verts_len > 1:
2981                 col.separator()
2982                 col.operator("mesh.edge_face_add", text="New Edge/Face from Vertices")
2983                 col.operator("mesh.vert_connect_path", text="Connect Vertex Path")
2984                 col.operator("mesh.vert_connect", text="Connect Vertex Pairs")
2985
2986             col.separator()
2987
2988             # Deform Operators
2989             col.operator("transform.push_pull", text="Push/Pull")
2990             col.operator("transform.shrink_fatten", text="Shrink/Fatten")
2991             col.operator("transform.shear", text="Shear")
2992             col.operator("transform.vert_slide", text="Slide Vertices")
2993             col.operator("transform.vertex_random", text="Randomize Vertices")
2994             col.operator("mesh.vertices_smooth", text="Smooth Vertices")
2995             col.operator("mesh.vertices_smooth_laplacian", text="Smooth Laplacian")
2996
2997             col.separator()
2998
2999             col.menu("VIEW3D_MT_mirror", text="Mirror Vertices")
3000             col.menu("VIEW3D_MT_snap", text="Snap Vertices")
3001
3002             col.separator()
3003
3004             # Removal Operators
3005             if selected_verts_len > 1:
3006                 col.operator("mesh.merge", text="Merge Vertices...")
3007                 col.operator("mesh.remove_doubles", text="Remove Double Vertices")
3008             col.operator("mesh.dissolve_verts")
3009             col.operator("mesh.delete", text="Delete Vertices").type = 'VERT'
3010
3011         if is_edge_mode:
3012             render = context.scene.render
3013
3014             col = row.column()
3015             col.label(text="Edge Context Menu", icon='EDGESEL')
3016             col.separator()
3017
3018             # Additive Operators
3019             col.operator("mesh.subdivide", text="Subdivide")
3020
3021             col.separator()
3022
3023             col.operator("mesh.extrude_edges_move", text="Extrude Edges"),
3024             col.operator("mesh.bevel", text="Bevel Edges").vertex_only = False
3025             if selected_edges_len >= 2:
3026                 col.operator("mesh.bridge_edge_loops")
3027             if selected_edges_len >= 1:
3028                 col.operator("mesh.edge_face_add", text="New Face from Edges")
3029             if selected_edges_len >= 2:
3030                 col.operator("mesh.fill")
3031
3032             col.separator()
3033
3034             col.operator("mesh.loopcut_slide")
3035             col.operator("mesh.offset_edge_loops_slide")
3036             col.operator("mesh.knife_tool")
3037             col.operator("mesh.bisect")
3038             col.operator("mesh.bridge_edge_loops", text="Bridge Edge Loops")
3039
3040             col.separator()
3041
3042             # Deform Operators
3043             col.operator("mesh.edge_rotate", text="Rotate Edge CW").use_ccw = False
3044             col.operator("transform.edge_slide")
3045             col.operator("mesh.edge_split")
3046
3047             col.separator()
3048
3049             # Edge Flags
3050             col.operator("transform.edge_crease")
3051             col.operator("transform.edge_bevelweight")
3052
3053             col.separator()
3054
3055             col.operator("mesh.mark_seam").clear = False
3056             col.operator("mesh.mark_seam", text="Clear Seam").clear = True
3057
3058             col.separator()
3059
3060             col.operator("mesh.mark_sharp")
3061             col.operator("mesh.mark_sharp", text="Clear Sharp").clear = True
3062
3063             if render.use_freestyle:
3064                 col.separator()
3065
3066                 col.operator("mesh.mark_freestyle_edge").clear = False
3067                 col.operator("mesh.mark_freestyle_edge", text="Clear Freestyle Edge").clear = True
3068
3069             col.separator()
3070
3071             # Removal Operators
3072             col.operator("mesh.unsubdivide")
3073             col.operator("mesh.dissolve_edges")
3074             col.operator("mesh.delete", text="Delete Edges").type = 'EDGE'
3075
3076         if is_face_mode:
3077             col = row.column()
3078
3079             col.label(text="Face Context Menu", icon='FACESEL')
3080             col.separator()
3081
3082             # Additive Operators
3083             col.operator("mesh.subdivide", text="Subdivide")
3084
3085             col.separator()
3086
3087             col.operator("view3d.edit_mesh_extrude_move_normal", text="Extrude Faces"),
3088             col.operator("view3d.edit_mesh_extrude_move_shrink_fatten", text="Extrude Faces Along Normals"),
3089             col.operator("mesh.extrude_faces_move", text="Extrude Individual Faces"),
3090
3091             col.operator("mesh.inset"),
3092             col.operator("mesh.poke")
3093
3094             if selected_faces_len >= 2:
3095                 col.operator("mesh.bridge_edge_loops", text="Bridge Faces")
3096
3097             col.separator()
3098
3099             # Modify Operators
3100             col.menu("VIEW3D_MT_uv_map", text="UV Unwrap Faces")
3101
3102             col.separator()
3103
3104             props = col.operator("mesh.quads_convert_to_tris")
3105             props.quad_method = props.ngon_method = 'BEAUTY'
3106             col.operator("mesh.tris_convert_to_quads")
3107
3108             col.separator()
3109
3110             col.operator("mesh.faces_shade_smooth")
3111             col.operator("mesh.faces_shade_flat")
3112
3113             col.separator()
3114
3115             # Removal Operators
3116             col.operator("mesh.unsubdivide")
3117             col.operator("mesh.dissolve_faces")
3118             col.operator("mesh.delete", text="Delete Faces").type = 'FACE'
3119
3120
3121 class VIEW3D_MT_edit_mesh_select_mode(Menu):
3122     bl_label = "Mesh Select Mode"
3123
3124     def draw(self, context):
3125         layout = self.layout
3126
3127         layout.operator_context = 'INVOKE_REGION_WIN'
3128         layout.operator("mesh.select_mode", text="Vertex", icon='VERTEXSEL').type = 'VERT'
3129         layout.operator("mesh.select_mode", text="Edge", icon='EDGESEL').type = 'EDGE'
3130         layout.operator("mesh.select_mode", text="Face", icon='FACESEL').type = 'FACE'
3131
3132
3133 class VIEW3D_MT_edit_mesh_extrude(Menu):
3134     bl_label = "Extrude"
3135
3136     _extrude_funcs = {
3137         'VERT': lambda layout:
3138             layout.operator("mesh.extrude_vertices_move", text="Extrude Vertices"),
3139         'EDGE': lambda layout:
3140             layout.operator("mesh.extrude_edges_move", text="Extrude Edges"),
3141         'REGION': lambda layout:
3142             layout.operator("view3d.edit_mesh_extrude_move_normal", text="Extrude Faces"),
3143         'REGION_VERT_NORMAL': lambda layout:
3144             layout.operator("view3d.edit_mesh_extrude_move_shrink_fatten", text="Extrude Faces Along Normals"),
3145         'FACE': lambda layout:
3146             layout.operator("mesh.extrude_faces_move", text="Extrude Individual Faces"),
3147     }
3148
3149     @staticmethod
3150     def extrude_options(context):
3151         tool_settings = context.tool_settings
3152         select_mode = tool_settings.mesh_select_mode
3153         mesh = context.object.data
3154
3155         menu = []
3156         if mesh.total_face_sel:
3157             menu += ['REGION', 'REGION_VERT_NORMAL', 'FACE']
3158         if mesh.total_edge_sel and (select_mode[0] or select_mode[1]):
3159             menu += ['EDGE']
3160         if mesh.total_vert_sel and select_mode[0]:
3161             menu += ['VERT']
3162
3163         # should never get here
3164         return menu
3165
3166     def draw(self, context):
3167         layout = self.layout
3168         layout.operator_context = 'INVOKE_REGION_WIN'
3169
3170         for menu_id in self.extrude_options(context):
3171             self._extrude_funcs[menu_id](layout)
3172
3173
3174 class VIEW3D_MT_edit_mesh_vertices(Menu):
3175     bl_label = "Vertex"
3176
3177     def draw(self, context):
3178         layout = self.layout
3179         layout.operator_context = 'INVOKE_REGION_WIN'
3180
3181         layout.operator("mesh.extrude_vertices_move", text="Extrude Vertices"),
3182         layout.operator("mesh.bevel", text="Bevel Vertices").vertex_only = True
3183
3184         layout.separator()
3185
3186         layout.operator("mesh.edge_face_add", text="New Edge/Face from Vertices")
3187         layout.operator("mesh.vert_connect_path", text="Connect Vertex Path")
3188         layout.operator("mesh.vert_connect", text="Connect Vertex Pairs")
3189
3190         layout.separator()
3191
3192         props = layout.operator("mesh.rip_move", text="Rip Vertices")
3193         props.MESH_OT_rip.use_fill = False
3194         props = layout.operator("mesh.rip_move", text="Rip Vertices and Fill")
3195         props.MESH_OT_rip.use_fill = True
3196         layout.operator("mesh.rip_edge_move", text="Rip Vertices and Extend")
3197
3198         layout.separator()
3199
3200         layout.operator("transform.vert_slide", text="Slide Vertices")
3201         layout.operator("mesh.vertices_smooth", text="Smooth Vertices")
3202
3203         layout.separator()
3204
3205         layout.operator("mesh.blend_from_shape")
3206         layout.operator("mesh.shape_propagate_to_all", text="Propagate to Shapes")
3207
3208         layout.separator()
3209
3210         layout.operator("mesh.merge", text="Merge Vertices")
3211         layout.operator("mesh.remove_doubles", text="Remove Double Vertices")
3212
3213         layout.separator()
3214
3215         layout.menu("VIEW3D_MT_vertex_group")
3216         layout.menu("VIEW3D_MT_hook")
3217
3218         layout.separator()
3219
3220         layout.operator("object.vertex_parent_set")
3221
3222
3223 class VIEW3D_MT_edit_mesh_edges_data(Menu):
3224     bl_label = "Edge Data"
3225
3226     def draw(self, context):
3227         layout = self.layout
3228
3229         render = context.scene.render
3230
3231         layout.operator_context = 'INVOKE_REGION_WIN'
3232
3233         layout.operator("transform.edge_crease")
3234         layout.operator("transform.edge_bevelweight")
3235
3236         layout.separator()
3237
3238         layout.operator("mesh.mark_seam").clear = False
3239         layout.operator("mesh.mark_seam", text="Clear Seam").clear = True
3240
3241         layout.separator()
3242
3243         layout.operator("mesh.mark_sharp")
3244         layout.operator("mesh.mark_sharp", text="Clear Sharp").clear = True
3245
3246         layout.operator("mesh.mark_sharp", text="Mark Sharp from Vertices").use_verts = True
3247         props = layout.operator("mesh.mark_sharp", text="Clear Sharp from Vertices")
3248         props.use_verts = True
3249         props.clear = True
3250
3251         if render.use_freestyle:
3252             layout.separator()
3253
3254             layout.operator("mesh.mark_freestyle_edge").clear = False
3255             layout.operator("mesh.mark_freestyle_edge", text="Clear Freestyle Edge").clear = True
3256
3257
3258 class VIEW3D_MT_edit_mesh_edges(Menu):
3259     bl_label = "Edge"
3260
3261     def draw(self, context):
3262         layout = self.layout
3263
3264         with_freestyle = bpy.app.build_options.freestyle
3265
3266         layout.operator_context = 'INVOKE_REGION_WIN'
3267
3268         layout.operator("mesh.extrude_edges_move", text="Extrude Edges"),
3269         layout.operator("mesh.bevel", text="Bevel Edges").vertex_only = False
3270         layout.operator("mesh.bridge_edge_loops")
3271
3272         layout.separator()
3273
3274         layout.operator("mesh.subdivide")
3275         layout.operator("mesh.subdivide_edgering")
3276         layout.operator("mesh.unsubdivide")
3277
3278         layout.separator()
3279
3280         layout.operator("mesh.edge_rotate", text="Rotate Edge CW").use_ccw = False
3281         layout.operator("mesh.edge_rotate", text="Rotate Edge CCW").use_ccw = True
3282
3283         layout.separator()
3284
3285         layout.operator("transform.edge_slide")
3286         layout.operator("mesh.edge_split")
3287
3288         layout.separator()
3289
3290         layout.operator("transform.edge_crease")
3291         layout.operator("transform.edge_bevelweight")
3292
3293         layout.separator()
3294
3295         layout.operator("mesh.mark_seam").clear = False
3296         layout.operator("mesh.mark_seam", text="Clear Seam").clear = True
3297
3298         layout.separator()
3299
3300         layout.operator("mesh.mark_sharp")
3301         layout.operator("mesh.mark_sharp", text="Clear Sharp").clear = True
3302
3303         layout.operator("mesh.mark_sharp", text="Mark Sharp from Vertices").use_verts = True
3304         props = layout.operator("mesh.mark_sharp", text="Clear Sharp from Vertices")
3305         props.use_verts = True
3306         props.clear = True
3307
3308         if with_freestyle:
3309             layout.separator()
3310
3311             layout.operator("mesh.mark_freestyle_edge").clear = False
3312             layout.operator("mesh.mark_freestyle_edge", text="Clear Freestyle Edge").clear = True
3313
3314
3315 class VIEW3D_MT_edit_mesh_faces_data(Menu):
3316     bl_label = "Face Data"
3317
3318     def draw(self, context):
3319         layout = self.layout
3320
3321         with_freestyle = bpy.app.build_options.freestyle
3322
3323         layout.operator_context = 'INVOKE_REGION_WIN'
3324
3325         layout.operator("mesh.colors_rotate")
3326         layout.operator("mesh.colors_reverse")
3327
3328         layout.separator()
3329
3330         layout.operator("mesh.uvs_rotate")
3331         layout.operator("mesh.uvs_reverse")
3332
3333         layout.separator()
3334
3335         if with_freestyle:
3336             layout.operator("mesh.mark_freestyle_face").clear = False
3337             layout.operator("mesh.mark_freestyle_face", text="Clear Freestyle Face").clear = True
3338
3339
3340 class VIEW3D_MT_edit_mesh_faces(Menu):
3341     bl_label = "Face"
3342     bl_idname = "VIEW3D_MT_edit_mesh_faces"
3343
3344     def draw(self, context):
3345         layout = self.layout
3346
3347         layout.operator_context = 'INVOKE_REGION_WIN'
3348
3349         layout.operator("view3d.edit_mesh_extrude_move_normal", text="Extrude Faces"),
3350         layout.operator("view3d.edit_mesh_extrude_move_shrink_fatten", text="Extrude Faces Along Normals"),
3351         layout.operator("mesh.extrude_faces_move", text="Extrude Individual Faces"),
3352
3353         layout.separator()
3354
3355         layout.operator("mesh.inset")
3356         layout.operator("mesh.poke")
3357         props = layout.operator("mesh.quads_convert_to_tris")
3358         props.quad_method = props.ngon_method = 'BEAUTY'
3359         layout.operator("mesh.tris_convert_to_quads")
3360         layout.operator("mesh.solidify", text="Solidify Faces")
3361         layout.operator("mesh.wireframe")
3362
3363         layout.separator()
3364
3365         layout.operator("mesh.fill")
3366         layout.operator("mesh.fill_grid")
3367         layout.operator("mesh.beautify_fill")
3368
3369         layout.separator()
3370
3371         layout.operator("mesh.intersect")
3372         layout.operator("mesh.intersect_boolean")
3373
3374         layout.separator()
3375
3376         layout.operator("mesh.face_split_by_edges")
3377
3378         layout.separator()
3379
3380         layout.operator("mesh.faces_shade_smooth")
3381         layout.operator("mesh.faces_shade_flat")
3382
3383         layout.separator()
3384
3385         layout.menu("VIEW3D_MT_edit_mesh_faces_data")
3386
3387
3388 class VIEW3D_MT_edit_mesh_normals(Menu):
3389     bl_label = "Normals"
3390
3391     def draw(self, context):
3392         layout = self.layout
3393
3394         layout.operator("mesh.normals_make_consistent", text="Recalculate Outside").inside = False
3395         layout.operator("mesh.normals_make_consistent", text="Recalculate Inside").inside = True
3396
3397         layout.separator()
3398
3399         layout.operator("mesh.flip_normals")
3400         layout.operator("mesh.set_normals_from_faces", text="Set From Faces")
3401
3402         layout.operator("transform.rotate_normal", text="Rotate Normal")
3403         layout.operator("mesh.point_normals", text="Point normals to target")
3404
3405         layout.operator("mesh.merge_normals", text="Merge")
3406         layout.operator("mesh.split_normals", text="Split")
3407
3408         layout.operator("mesh.average_normals", text="Average Normals")
3409
3410         layout.label(text="Normal Vector")
3411
3412         layout.operator("mesh.normals_tools", text="Copy").mode = 'COPY'
3413         layout.operator("mesh.normals_tools", text="Paste").mode = 'PASTE'
3414
3415         layout.operator("mesh.normals_tools", text="Multiply").mode = 'MULTIPLY'
3416         layout.operator("mesh.normals_tools", text="Add").mode = 'ADD'
3417
3418         layout.operator("mesh.normals_tools", text="Reset").mode = 'RESET'
3419
3420         layout.operator("mesh.smoothen_normals", text="Smoothen")
3421
3422         layout.label(text="Face Strength")
3423         layout.operator("mesh.mod_weighted_strength", text="Face Select", icon='FACESEL').set = False
3424         layout.operator("mesh.mod_weighted_strength", text="Set Strength", icon='ADD').set = True
3425
3426
3427 class VIEW3D_MT_edit_mesh_shading(Menu):
3428     bl_label = "Shading"
3429
3430     def draw(self, context):
3431         layout = self.layout
3432
3433         layout.operator("mesh.faces_shade_smooth", text="Smooth Faces")
3434         layout.operator("mesh.faces_shade_flat", text="Flat Faces")
3435
3436         layout.separator()
3437
3438         layout.operator("mesh.mark_sharp", text="Smooth Edges").clear = True
3439         layout.operator("mesh.mark_sharp", text="Sharp Edges")
3440
3441         layout.separator()
3442
3443         props = layout.operator("mesh.mark_sharp", text="Smooth Vertices")
3444         props.use_verts = True
3445         props.clear = True
3446
3447         layout.operator("mesh.mark_sharp", text="Sharp Vertices").use_verts = True
3448
3449
3450 class VIEW3D_MT_edit_mesh_weights(Menu):
3451     bl_label = "Weights"
3452
3453     def draw(self, context):
3454         VIEW3D_MT_paint_weight.draw_generic(self.layout, is_editmode=True)
3455
3456
3457 class VIEW3D_MT_edit_mesh_clean(Menu):
3458     bl_label = "Clean Up"
3459
3460     def draw(self, context):
3461         layout = self.layout
3462
3463         layout.operator("mesh.delete_loose")
3464
3465         layout.separator()
3466
3467         layout.operator("mesh.decimate")
3468         layout.operator("mesh.dissolve_degenerate")
3469         layout.operator("mesh.dissolve_limited")
3470         layout.operator("mesh.face_make_planar")
3471
3472         layout.separator()
3473
3474         layout.operator("mesh.vert_connect_nonplanar")
3475         layout.operator("mesh.vert_connect_concave")
3476         layout.operator("mesh.remove_doubles")
3477         layout.operator("mesh.fill_holes")
3478
3479
3480 class VIEW3D_MT_edit_mesh_delete(Menu):
3481     bl_label = "Delete"
3482
3483     def draw(self, context):
3484         layout = self.layout
3485
3486         layout.operator_enum("mesh.delete", "type")
3487
3488         layout.separator()
3489
3490         layout.operator("mesh.dissolve_verts")
3491         layout.operator("mesh.dissolve_edges")
3492         layout.operator("mesh.dissolve_faces")
3493
3494         layout.separator()
3495
3496         layout.operator("mesh.dissolve_limited")
3497
3498         layout.separator()
3499
3500         layout.operator("mesh.edge_collapse")
3501         layout.operator("mesh.delete_edgeloop", text="Edge Loops")
3502
3503
3504 class VIEW3D_MT_edit_mesh_showhide(ShowHideMenu, Menu):
3505     _operator_name = "mesh"
3506
3507
3508 class VIEW3D_MT_edit_gpencil_delete(Menu):
3509     bl_label = "Delete"
3510
3511     def draw(self, context):
3512         layout = self.layout
3513
3514         layout.operator_enum("gpencil.delete", "type")
3515
3516         layout.separator()
3517
3518         layout.operator_enum("gpencil.dissolve", "type")
3519
3520         layout.separator()
3521
3522         layout.operator("gpencil.active_frames_delete_all")
3523 # Edit Curve
3524 # draw_curve is used by VIEW3D_MT_edit_curve and VIEW3D_MT_edit_surface
3525
3526
3527 def draw_curve(self, context):
3528     layout = self.layout
3529
3530     layout.menu("VIEW3D_MT_transform")
3531     layout.menu("VIEW3D_MT_mirror")
3532     layout.menu("VIEW3D_MT_snap")
3533
3534     layout.separator()
3535
3536     layout.operator("curve.spin")
3537     layout.operator("curve.duplicate_move")
3538
3539     layout.separator()
3540
3541     layout.operator("curve.split")
3542     layout.operator("curve.separate")
3543     layout.operator("curve.cyclic_toggle")
3544     layout.operator_menu_enum("curve.spline_type_set", "type")
3545
3546     layout.separator()
3547
3548     layout.menu("VIEW3D_MT_edit_curve_showhide")
3549     layout.menu("VIEW3D_MT_edit_curve_clean")
3550     layout.menu("VIEW3D_MT_edit_curve_delete")
3551
3552
3553 class VIEW3D_MT_edit_curve(Menu):
3554     bl_label = "Curve"
3555
3556     draw = draw_curve
3557
3558
3559 class VIEW3D_MT_edit_curve_ctrlpoints(Menu):
3560     bl_label = "Control Points"
3561