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> 20import bpy 21from bpy.types import Header, Menu, Panel 22 23 24class TOPBAR_HT_upper_bar(Header): 25 bl_space_type = 'TOPBAR' 26 27 def draw(self, context): 28 region = context.region 29 30 if region.alignment == 'RIGHT': 31 self.draw_right(context) 32 else: 33 self.draw_left(context) 34 35 def draw_left(self, context): 36 layout = self.layout 37 38 window = context.window 39 screen = context.screen 40 41 TOPBAR_MT_editor_menus.draw_collapsible(context, layout) 42 43 layout.separator() 44 45 if not screen.show_fullscreen: 46 layout.template_ID_tabs( 47 window, "workspace", 48 new="workspace.add", 49 menu="TOPBAR_MT_workspace_menu", 50 ) 51 else: 52 layout.operator( 53 "screen.back_to_previous", 54 icon='SCREEN_BACK', 55 text="Back to Previous", 56 ) 57 58 def draw_right(self, context): 59 layout = self.layout 60 61 window = context.window 62 screen = context.screen 63 scene = window.scene 64 65 # If statusbar is hidden, still show messages at the top 66 if not screen.show_statusbar: 67 layout.template_reports_banner() 68 layout.template_running_jobs() 69 70 # Active workspace view-layer is retrieved through window, not through workspace. 71 layout.template_ID(window, "scene", new="scene.new", 72 unlink="scene.delete") 73 74 row = layout.row(align=True) 75 row.template_search( 76 window, "view_layer", 77 scene, "view_layers", 78 new="scene.view_layer_add", 79 unlink="scene.view_layer_remove") 80 81 82class TOPBAR_PT_tool_settings_extra(Panel): 83 """ 84 Popover panel for adding extra options that don't fit in the tool settings header 85 """ 86 bl_idname = "TOPBAR_PT_tool_settings_extra" 87 bl_region_type = 'HEADER' 88 bl_space_type = 'TOPBAR' 89 bl_label = "Extra Options" 90 91 def draw(self, context): 92 from bl_ui.space_toolsystem_common import ToolSelectPanelHelper 93 layout = self.layout 94 95 # Get the active tool 96 space_type, mode = ToolSelectPanelHelper._tool_key_from_context( 97 context) 98 cls = ToolSelectPanelHelper._tool_class_from_space_type(space_type) 99 item, tool, _ = cls._tool_get_active( 100 context, space_type, mode, with_icon=True) 101 if item is None: 102 return 103 104 # Draw the extra settings 105 item.draw_settings(context, layout, tool, extra=True) 106 107 108class TOPBAR_PT_tool_fallback(Panel): 109 bl_space_type = 'VIEW_3D' 110 bl_region_type = 'HEADER' 111 bl_label = "Layers" 112 bl_ui_units_x = 8 113 114 def draw(self, context): 115 from bl_ui.space_toolsystem_common import ToolSelectPanelHelper 116 layout = self.layout 117 118 tool_settings = context.tool_settings 119 ToolSelectPanelHelper.draw_fallback_tool_items(layout, context) 120 if tool_settings.workspace_tool_type == 'FALLBACK': 121 tool = context.tool 122 ToolSelectPanelHelper.draw_active_tool_fallback( 123 context, layout, tool) 124 125 126class TOPBAR_PT_gpencil_layers(Panel): 127 bl_space_type = 'VIEW_3D' 128 bl_region_type = 'HEADER' 129 bl_label = "Layers" 130 bl_ui_units_x = 14 131 132 @classmethod 133 def poll(cls, context): 134 if context.gpencil_data is None: 135 return False 136 137 ob = context.object 138 if ob is not None and ob.type == 'GPENCIL': 139 return True 140 141 return False 142 143 def draw(self, context): 144 layout = self.layout 145 gpd = context.gpencil_data 146 147 # Grease Pencil data... 148 if (gpd is None) or (not gpd.layers): 149 layout.operator("gpencil.layer_add", text="New Layer") 150 else: 151 self.draw_layers(context, layout, gpd) 152 153 def draw_layers(self, context, layout, gpd): 154 row = layout.row() 155 156 col = row.column() 157 layer_rows = 10 158 col.template_list("GPENCIL_UL_layer", "", gpd, "layers", gpd.layers, "active_index", 159 rows=layer_rows, sort_reverse=True, sort_lock=True) 160 161 gpl = context.active_gpencil_layer 162 if gpl: 163 srow = col.row(align=True) 164 srow.prop(gpl, "blend_mode", text="Blend") 165 166 srow = col.row(align=True) 167 srow.prop(gpl, "opacity", text="Opacity", slider=True) 168 srow.prop(gpl, "use_mask_layer", text="", 169 icon='MOD_MASK' if gpl.use_mask_layer else 'LAYER_ACTIVE') 170 171 srow = col.row(align=True) 172 srow.prop(gpl, "use_lights") 173 174 col = row.column() 175 176 sub = col.column(align=True) 177 sub.operator("gpencil.layer_add", icon='ADD', text="") 178 sub.operator("gpencil.layer_remove", icon='REMOVE', text="") 179 180 gpl = context.active_gpencil_layer 181 if gpl: 182 sub.menu("GPENCIL_MT_layer_context_menu", 183 icon='DOWNARROW_HLT', text="") 184 185 if len(gpd.layers) > 1: 186 col.separator() 187 188 sub = col.column(align=True) 189 sub.operator("gpencil.layer_move", 190 icon='TRIA_UP', text="").type = 'UP' 191 sub.operator("gpencil.layer_move", 192 icon='TRIA_DOWN', text="").type = 'DOWN' 193 194 col.separator() 195 196 sub = col.column(align=True) 197 sub.operator("gpencil.layer_isolate", icon='HIDE_OFF', 198 text="").affect_visibility = True 199 sub.operator("gpencil.layer_isolate", icon='LOCKED', 200 text="").affect_visibility = False 201 202 203class TOPBAR_MT_editor_menus(Menu): 204 bl_idname = "TOPBAR_MT_editor_menus" 205 bl_label = "" 206 207 def draw(self, context): 208 layout = self.layout 209 210 # Allow calling this menu directly (this might not be a header area). 211 if getattr(context.area, "show_menus", False): 212 layout.menu("TOPBAR_MT_app", text="", icon='BLENDER') 213 else: 214 layout.menu("TOPBAR_MT_app", text="Blender") 215 216 layout.menu("TOPBAR_MT_file") 217 layout.menu("TOPBAR_MT_edit") 218 219 layout.menu("TOPBAR_MT_render") 220 221 layout.menu("TOPBAR_MT_window") 222 layout.menu("TOPBAR_MT_help") 223 224 225class TOPBAR_MT_app(Menu): 226 bl_label = "Blender" 227 228 def draw(self, _context): 229 layout = self.layout 230 231 layout.operator("wm.splash") 232 layout.operator("wm.splash_about") 233 234 layout.separator() 235 236 layout.operator("preferences.app_template_install", 237 text="Install Application Template...") 238 239 layout.separator() 240 241 layout.menu("TOPBAR_MT_app_system") 242 243 244class TOPBAR_MT_file_cleanup(Menu): 245 bl_label = "Clean Up" 246 247 def draw(self, context): 248 layout = self.layout 249 layout.separator() 250 251 layout.operator("outliner.orphans_purge") 252 253 254class TOPBAR_MT_file(Menu): 255 bl_label = "File" 256 257 def draw(self, context): 258 layout = self.layout 259 260 layout.operator_context = 'INVOKE_AREA' 261 layout.menu("TOPBAR_MT_file_new", text="New", icon='FILE_NEW') 262 layout.operator("wm.open_mainfile", text="Open...", icon='FILE_FOLDER') 263 layout.menu("TOPBAR_MT_file_open_recent") 264 layout.operator("wm.revert_mainfile") 265 layout.menu("TOPBAR_MT_file_recover") 266 267 layout.separator() 268 269 layout.operator_context = 'EXEC_AREA' if context.blend_data.is_saved else 'INVOKE_AREA' 270 layout.operator("wm.save_mainfile", text="Save", icon='FILE_TICK') 271 272 layout.operator_context = 'INVOKE_AREA' 273 layout.operator("wm.save_as_mainfile", text="Save As...") 274 layout.operator_context = 'INVOKE_AREA' 275 layout.operator("wm.save_as_mainfile", text="Save Copy...").copy = True 276 277 layout.separator() 278 279 layout.operator_context = 'INVOKE_AREA' 280 layout.operator("wm.link", text="Link...", icon='LINK_BLEND') 281 layout.operator("wm.append", text="Append...", icon='APPEND_BLEND') 282 layout.menu("TOPBAR_MT_file_previews") 283 284 layout.separator() 285 286 layout.menu("TOPBAR_MT_file_import", icon='IMPORT') 287 layout.menu("TOPBAR_MT_file_export", icon='EXPORT') 288 289 layout.separator() 290 291 layout.menu("TOPBAR_MT_file_external_data") 292 layout.menu("TOPBAR_MT_file_cleanup") 293 294 layout.separator() 295 296 layout.menu("TOPBAR_MT_file_defaults") 297 298 layout.separator() 299 300 layout.operator("wm.quit_blender", text="Quit", icon='QUIT') 301 302 303class TOPBAR_MT_file_new(Menu): 304 bl_label = "New File" 305 306 @staticmethod 307 def app_template_paths(): 308 import os 309 310 template_paths = bpy.utils.app_template_paths() 311 312 # Expand template paths. 313 314 # Use a set to avoid duplicate user/system templates. 315 # This is a corner case, but users managed to do it! T76849. 316 app_templates = set() 317 for path in template_paths: 318 for d in os.listdir(path): 319 if d.startswith(("__", ".")): 320 continue 321 template = os.path.join(path, d) 322 if os.path.isdir(template): 323 app_templates.add(d) 324 325 return sorted(app_templates) 326 327 @staticmethod 328 def draw_ex(layout, _context, *, use_splash=False, use_more=False): 329 layout.operator_context = 'INVOKE_DEFAULT' 330 331 # Limit number of templates in splash screen, spill over into more menu. 332 paths = TOPBAR_MT_file_new.app_template_paths() 333 splash_limit = 5 334 335 if use_splash: 336 icon = 'FILE_NEW' 337 show_more = len(paths) > (splash_limit - 1) 338 if show_more: 339 paths = paths[:splash_limit - 2] 340 elif use_more: 341 icon = 'FILE_NEW' 342 paths = paths[splash_limit - 2:] 343 show_more = False 344 else: 345 icon = 'NONE' 346 show_more = False 347 348 # Draw application templates. 349 if not use_more: 350 props = layout.operator( 351 "wm.read_homefile", text="General", icon=icon) 352 props.app_template = "" 353 354 for d in paths: 355 props = layout.operator( 356 "wm.read_homefile", 357 text=bpy.path.display_name(d), 358 icon=icon, 359 ) 360 props.app_template = d 361 362 layout.operator_context = 'EXEC_DEFAULT' 363 364 if show_more: 365 layout.menu("TOPBAR_MT_templates_more", text="...") 366 367 def draw(self, context): 368 TOPBAR_MT_file_new.draw_ex(self.layout, context) 369 370 371class TOPBAR_MT_file_recover(Menu): 372 bl_label = "Recover" 373 374 def draw(self, _context): 375 layout = self.layout 376 377 layout.operator("wm.recover_last_session", text="Last Session") 378 layout.operator("wm.recover_auto_save", text="Auto Save...") 379 380 381class TOPBAR_MT_file_defaults(Menu): 382 bl_label = "Defaults" 383 384 def draw(self, context): 385 layout = self.layout 386 prefs = context.preferences 387 388 layout.operator_context = 'INVOKE_AREA' 389 390 if any(bpy.utils.app_template_paths()): 391 app_template = prefs.app_template 392 else: 393 app_template = None 394 395 if app_template: 396 layout.label(text=bpy.path.display_name( 397 app_template, has_ext=False)) 398 399 layout.operator("wm.save_homefile") 400 props = layout.operator("wm.read_factory_settings") 401 if app_template: 402 props.app_template = app_template 403 404 405# Include technical operators here which would otherwise have no way for users to access. 406class TOPBAR_MT_app_system(Menu): 407 bl_label = "System" 408 409 def draw(self, _context): 410 layout = self.layout 411 412 layout.operator("script.reload") 413 414 layout.separator() 415 416 layout.operator("wm.memory_statistics") 417 layout.operator("wm.debug_menu") 418 layout.operator_menu_enum("wm.redraw_timer", "type") 419 420 layout.separator() 421 422 layout.operator("screen.spacedata_cleanup") 423 424 425class TOPBAR_MT_templates_more(Menu): 426 bl_label = "Templates" 427 428 def draw(self, context): 429 bpy.types.TOPBAR_MT_file_new.draw_ex( 430 self.layout, context, use_more=True) 431 432 433class TOPBAR_MT_file_import(Menu): 434 bl_idname = "TOPBAR_MT_file_import" 435 bl_label = "Import" 436 bl_owner_use_filter = False 437 438 def draw(self, _context): 439 if bpy.app.build_options.collada: 440 self.layout.operator("wm.collada_import", 441 text="Collada (Default) (.dae)") 442 if bpy.app.build_options.alembic: 443 self.layout.operator("wm.alembic_import", text="Alembic (.abc)") 444 445 446class TOPBAR_MT_file_export(Menu): 447 bl_idname = "TOPBAR_MT_file_export" 448 bl_label = "Export" 449 bl_owner_use_filter = False 450 451 def draw(self, context): 452 if bpy.app.build_options.collada: 453 self.layout.operator("wm.collada_export", 454 text="Collada (Default) (.dae)") 455 if bpy.app.build_options.alembic: 456 self.layout.operator("wm.alembic_export", text="Alembic (.abc)") 457 if bpy.app.build_options.usd: 458 self.layout.operator( 459 "wm.usd_export", text="Universal Scene Description (.usd, .usdc, .usda)") 460 461 462class TOPBAR_MT_file_external_data(Menu): 463 bl_label = "External Data" 464 465 def draw(self, _context): 466 layout = self.layout 467 468 icon = 'CHECKBOX_HLT' if bpy.data.use_autopack else 'CHECKBOX_DEHLT' 469 layout.operator("file.autopack_toggle", icon=icon) 470 471 layout.separator() 472 473 pack_all = layout.row() 474 pack_all.operator("file.pack_all") 475 pack_all.active = not bpy.data.use_autopack 476 477 unpack_all = layout.row() 478 unpack_all.operator("file.unpack_all") 479 unpack_all.active = not bpy.data.use_autopack 480 481 layout.separator() 482 483 layout.operator("file.make_paths_relative") 484 layout.operator("file.make_paths_absolute") 485 layout.operator("file.report_missing_files") 486 layout.operator("file.find_missing_files") 487 488 489class TOPBAR_MT_file_previews(Menu): 490 bl_label = "Data Previews" 491 492 def draw(self, _context): 493 layout = self.layout 494 495 layout.operator("wm.previews_ensure") 496 layout.operator("wm.previews_batch_generate") 497 498 layout.separator() 499 500 layout.operator("wm.previews_clear") 501 layout.operator("wm.previews_batch_clear") 502 503 504class TOPBAR_MT_render(Menu): 505 bl_label = "Render" 506 507 def draw(self, context): 508 layout = self.layout 509 510 rd = context.scene.render 511 512 layout.operator("render.render", text="Render Image", 513 icon='RENDER_STILL').use_viewport = True 514 props = layout.operator( 515 "render.render", text="Render Animation", icon='RENDER_ANIMATION') 516 props.animation = True 517 props.use_viewport = True 518 519 layout.separator() 520 521 layout.operator("sound.mixdown", text="Render Audio...") 522 523 layout.separator() 524 525 layout.operator("render.view_show", text="View Render") 526 layout.operator("render.play_rendered_anim", text="View Animation") 527 528 layout.separator() 529 530 layout.prop(rd, "use_lock_interface", text="Lock Interface") 531 532 533class TOPBAR_MT_edit(Menu): 534 bl_label = "Edit" 535 536 def draw(self, context): 537 layout = self.layout 538 539 show_developer = context.preferences.view.show_developer_ui 540 541 layout.operator("ed.undo") 542 layout.operator("ed.redo") 543 544 layout.separator() 545 546 layout.operator("ed.undo_history", text="Undo History...") 547 548 layout.separator() 549 550 layout.operator("screen.repeat_last") 551 layout.operator("screen.repeat_history", text="Repeat History...") 552 553 layout.separator() 554 555 layout.operator("screen.redo_last", text="Adjust Last Operation...") 556 557 layout.separator() 558 559 layout.operator("wm.search_menu", text="Menu Search...", icon='VIEWZOOM') 560 if show_developer: 561 layout.operator("wm.search_operator", text="Operator Search...", icon='VIEWZOOM') 562 563 layout.separator() 564 565 # Mainly to expose shortcut since this depends on the context. 566 props = layout.operator("wm.call_panel", text="Rename Active Item...") 567 props.name = "TOPBAR_PT_name" 568 props.keep_open = False 569 570 layout.operator("wm.batch_rename") 571 572 layout.separator() 573 574 # Should move elsewhere (impacts outliner & 3D view). 575 tool_settings = context.tool_settings 576 layout.prop(tool_settings, "lock_object_mode") 577 578 layout.separator() 579 580 layout.operator("screen.userpref_show", 581 text="Preferences...", icon='PREFERENCES') 582 583 584class TOPBAR_MT_window(Menu): 585 bl_label = "Window" 586 587 def draw(self, context): 588 import sys 589 590 layout = self.layout 591 592 layout.operator("wm.window_new") 593 layout.operator("wm.window_new_main") 594 595 layout.separator() 596 597 layout.operator("wm.window_fullscreen_toggle", icon='FULLSCREEN_ENTER') 598 599 layout.separator() 600 601 layout.operator("screen.workspace_cycle", 602 text="Next Workspace").direction = 'NEXT' 603 layout.operator("screen.workspace_cycle", 604 text="Previous Workspace").direction = 'PREV' 605 606 layout.separator() 607 608 layout.prop(context.screen, "show_statusbar") 609 610 layout.separator() 611 612 layout.operator("screen.screenshot") 613 614 if sys.platform[:3] == "win": 615 layout.separator() 616 layout.operator("wm.console_toggle", icon='CONSOLE') 617 618 if context.scene.render.use_multiview: 619 layout.separator() 620 layout.operator("wm.set_stereo_3d") 621 622 623class TOPBAR_MT_help(Menu): 624 bl_label = "Help" 625 626 def draw(self, context): 627 layout = self.layout 628 629 show_developer = context.preferences.view.show_developer_ui 630 631 layout.operator("wm.url_open_preset", text="Manual", 632 icon='HELP').type = 'MANUAL' 633 634 layout.operator( 635 "wm.url_open", text="Tutorials", icon='URL', 636 ).url = "https://www.blender.org/tutorials" 637 layout.operator( 638 "wm.url_open", text="Support", icon='URL', 639 ).url = "https://www.blender.org/support" 640 641 layout.separator() 642 643 layout.operator( 644 "wm.url_open", text="User Communities", icon='URL', 645 ).url = "https://www.blender.org/community/" 646 layout.operator( 647 "wm.url_open", text="Developer Community", icon='URL', 648 ).url = "https://devtalk.blender.org" 649 650 layout.separator() 651 652 layout.operator( 653 "wm.url_open", text="Python API Reference", icon='URL', 654 ).url = bpy.types.WM_OT_doc_view._prefix 655 656 if show_developer: 657 layout.operator( 658 "wm.url_open", text="Developer Documentation", icon='URL', 659 ).url = "https://wiki.blender.org/wiki/Main_Page" 660 661 layout.operator("wm.operator_cheat_sheet", icon='TEXT') 662 663 layout.separator() 664 665 layout.operator("wm.url_open_preset", 666 text="Report a Bug", icon='URL').type = 'BUG' 667 668 layout.separator() 669 670 layout.operator("wm.sysinfo") 671 672 673class TOPBAR_MT_file_context_menu(Menu): 674 bl_label = "File Context Menu" 675 676 def draw(self, _context): 677 layout = self.layout 678 679 layout.operator_context = 'INVOKE_AREA' 680 layout.menu("TOPBAR_MT_file_new", text="New", icon='FILE_NEW') 681 layout.operator("wm.open_mainfile", text="Open...", icon='FILE_FOLDER') 682 683 layout.separator() 684 685 layout.operator("wm.link", text="Link...", icon='LINK_BLEND') 686 layout.operator("wm.append", text="Append...", icon='APPEND_BLEND') 687 688 layout.separator() 689 690 layout.menu("TOPBAR_MT_file_import", icon='IMPORT') 691 layout.menu("TOPBAR_MT_file_export", icon='EXPORT') 692 693 layout.separator() 694 695 layout.operator("screen.userpref_show", 696 text="Preferences...", icon='PREFERENCES') 697 698 699class TOPBAR_MT_workspace_menu(Menu): 700 bl_label = "Workspace" 701 702 def draw(self, _context): 703 layout = self.layout 704 705 layout.operator("workspace.duplicate", 706 text="Duplicate", icon='DUPLICATE') 707 if len(bpy.data.workspaces) > 1: 708 layout.operator("workspace.delete", text="Delete", icon='REMOVE') 709 710 layout.separator() 711 712 layout.operator("workspace.reorder_to_front", 713 text="Reorder to Front", icon='TRIA_LEFT_BAR') 714 layout.operator("workspace.reorder_to_back", 715 text="Reorder to Back", icon='TRIA_RIGHT_BAR') 716 717 layout.separator() 718 719 # For key binding discoverability. 720 props = layout.operator("screen.workspace_cycle", 721 text="Previous Workspace") 722 props.direction = 'PREV' 723 props = layout.operator( 724 "screen.workspace_cycle", text="Next Workspace") 725 props.direction = 'NEXT' 726 727 728# Grease Pencil Object - Primitive curve 729class TOPBAR_PT_gpencil_primitive(Panel): 730 bl_space_type = 'VIEW_3D' 731 bl_region_type = 'HEADER' 732 bl_label = "Primitives" 733 734 def draw(self, context): 735 settings = context.tool_settings.gpencil_sculpt 736 737 layout = self.layout 738 # Curve 739 layout.template_curve_mapping( 740 settings, "thickness_primitive_curve", brush=True) 741 742 743# Only a popover 744class TOPBAR_PT_name(Panel): 745 bl_space_type = 'TOPBAR' # dummy 746 bl_region_type = 'HEADER' 747 bl_label = "Rename Active Item" 748 bl_ui_units_x = 14 749 750 def draw(self, context): 751 layout = self.layout 752 753 # Edit first editable button in popup 754 def row_with_icon(layout, icon): 755 row = layout.row() 756 row.activate_init = True 757 row.label(icon=icon) 758 return row 759 760 mode = context.mode 761 scene = context.scene 762 space = context.space_data 763 space_type = None if (space is None) else space.type 764 found = False 765 if space_type == 'SEQUENCE_EDITOR': 766 layout.label(text="Sequence Strip Name") 767 item = getattr(scene.sequence_editor, "active_strip") 768 if item: 769 row = row_with_icon(layout, 'SEQUENCE') 770 row.prop(item, "name", text="") 771 found = True 772 elif space_type == 'NODE_EDITOR': 773 layout.label(text="Node Label") 774 item = context.active_node 775 if item: 776 row = row_with_icon(layout, 'NODE') 777 row.prop(item, "label", text="") 778 found = True 779 else: 780 if mode == 'POSE' or (mode == 'WEIGHT_PAINT' and context.pose_object): 781 layout.label(text="Bone Name") 782 item = context.active_pose_bone 783 if item: 784 row = row_with_icon(layout, 'BONE_DATA') 785 row.prop(item, "name", text="") 786 found = True 787 elif mode == 'EDIT_ARMATURE': 788 layout.label(text="Bone Name") 789 item = context.active_bone 790 if item: 791 row = row_with_icon(layout, 'BONE_DATA') 792 row.prop(item, "name", text="") 793 found = True 794 else: 795 layout.label(text="Object Name") 796 item = context.object 797 if item: 798 row = row_with_icon(layout, 'OBJECT_DATA') 799 row.prop(item, "name", text="") 800 found = True 801 802 if not found: 803 row = row_with_icon(layout, 'ERROR') 804 row.label(text="No active item") 805 806 807classes = ( 808 TOPBAR_HT_upper_bar, 809 TOPBAR_MT_file_context_menu, 810 TOPBAR_MT_workspace_menu, 811 TOPBAR_MT_editor_menus, 812 TOPBAR_MT_app, 813 TOPBAR_MT_app_system, 814 TOPBAR_MT_file, 815 TOPBAR_MT_file_new, 816 TOPBAR_MT_file_recover, 817 TOPBAR_MT_file_defaults, 818 TOPBAR_MT_templates_more, 819 TOPBAR_MT_file_import, 820 TOPBAR_MT_file_export, 821 TOPBAR_MT_file_external_data, 822 TOPBAR_MT_file_cleanup, 823 TOPBAR_MT_file_previews, 824 TOPBAR_MT_edit, 825 TOPBAR_MT_render, 826 TOPBAR_MT_window, 827 TOPBAR_MT_help, 828 TOPBAR_PT_tool_fallback, 829 TOPBAR_PT_tool_settings_extra, 830 TOPBAR_PT_gpencil_layers, 831 TOPBAR_PT_gpencil_primitive, 832 TOPBAR_PT_name, 833) 834 835if __name__ == "__main__": # only for live edit. 836 from bpy.utils import register_class 837 for cls in classes: 838 register_class(cls) 839