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