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