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