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