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