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