3e7d6d986791acd0d30d0cdbd22d00d777e4af4c
[blender.git] / release / scripts / startup / bl_ui / space_topbar.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
23
24 class 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         layout.operator("wm.splash", text="", icon='BLENDER', emboss=False)
42
43         TOPBAR_MT_editor_menus.draw_collapsible(context, layout)
44
45         layout.separator()
46
47         if not screen.show_fullscreen:
48             layout.template_ID_tabs(
49                 window, "workspace",
50                 new="workspace.add",
51                 menu="TOPBAR_MT_workspace_menu",
52             )
53         else:
54             layout.operator(
55                 "screen.back_to_previous",
56                 icon='SCREEN_BACK',
57                 text="Back to Previous",
58             )
59
60     def draw_right(self, context):
61         layout = self.layout
62
63         window = context.window
64         screen = context.screen
65         scene = window.scene
66
67         # If statusbar is hidden, still show messages at the top
68         if not screen.show_statusbar:
69             layout.template_reports_banner()
70             layout.template_running_jobs()
71
72         # Active workspace view-layer is retrieved through window, not through workspace.
73         layout.template_ID(window, "scene", new="scene.new", unlink="scene.delete")
74
75         row = layout.row(align=True)
76         row.template_search(
77             window, "view_layer",
78             scene, "view_layers",
79             new="scene.view_layer_add",
80             unlink="scene.view_layer_remove")
81
82
83 class TOPBAR_PT_gpencil_layers(Panel):
84     bl_space_type = 'VIEW_3D'
85     bl_region_type = 'HEADER'
86     bl_label = "Layers"
87     bl_ui_units_x = 14
88
89     @classmethod
90     def poll(cls, context):
91         if context.gpencil_data is None:
92             return False
93
94         ob = context.object
95         if ob is not None and ob.type == 'GPENCIL':
96             return True
97
98         return False
99
100     def draw(self, context):
101         layout = self.layout
102         gpd = context.gpencil_data
103
104         # Grease Pencil data...
105         if (gpd is None) or (not gpd.layers):
106             layout.operator("gpencil.layer_add", text="New Layer")
107         else:
108             self.draw_layers(context, layout, gpd)
109
110     def draw_layers(self, context, layout, gpd):
111         row = layout.row()
112
113         col = row.column()
114         layer_rows = 10
115         col.template_list("GPENCIL_UL_layer", "", gpd, "layers", gpd.layers, "active_index",
116                           rows=layer_rows, sort_reverse=True, sort_lock=True)
117
118         gpl = context.active_gpencil_layer
119         if gpl:
120             srow = col.row(align=True)
121             srow.prop(gpl, "blend_mode", text="Blend")
122
123             srow = col.row(align=True)
124             srow.prop(gpl, "opacity", text="Opacity", slider=True)
125             srow.prop(gpl, "clamp_layer", text="",
126                       icon='MOD_MASK' if gpl.clamp_layer else 'LAYER_ACTIVE')
127
128             srow = col.row(align=True)
129             srow.prop(gpl, "use_solo_mode", text="Show Only On Keyframed")
130
131         col = row.column()
132
133         sub = col.column(align=True)
134         sub.operator("gpencil.layer_add", icon='ADD', text="")
135         sub.operator("gpencil.layer_remove", icon='REMOVE', text="")
136
137         gpl = context.active_gpencil_layer
138         if gpl:
139             sub.menu("GPENCIL_MT_layer_context_menu", icon='DOWNARROW_HLT', text="")
140
141             if len(gpd.layers) > 1:
142                 col.separator()
143
144                 sub = col.column(align=True)
145                 sub.operator("gpencil.layer_move", icon='TRIA_UP', text="").type = 'UP'
146                 sub.operator("gpencil.layer_move", icon='TRIA_DOWN', text="").type = 'DOWN'
147
148                 col.separator()
149
150                 sub = col.column(align=True)
151                 sub.operator("gpencil.layer_isolate", icon='LOCKED', text="").affect_visibility = False
152                 sub.operator("gpencil.layer_isolate", icon='HIDE_OFF', text="").affect_visibility = True
153
154
155 class TOPBAR_MT_editor_menus(Menu):
156     bl_idname = "TOPBAR_MT_editor_menus"
157     bl_label = ""
158
159     def draw(self, _context):
160         layout = self.layout
161         layout.menu("TOPBAR_MT_file")
162         layout.menu("TOPBAR_MT_edit")
163
164         layout.menu("TOPBAR_MT_render")
165
166         layout.menu("TOPBAR_MT_window")
167         layout.menu("TOPBAR_MT_help")
168
169
170 class TOPBAR_MT_file(Menu):
171     bl_label = "File"
172
173     def draw(self, context):
174         layout = self.layout
175
176         layout.operator_context = 'INVOKE_AREA'
177         layout.menu("TOPBAR_MT_file_new", text="New", icon='FILE_NEW')
178         layout.operator("wm.open_mainfile", text="Open...", icon='FILE_FOLDER')
179         layout.menu("TOPBAR_MT_file_open_recent")
180         layout.operator("wm.revert_mainfile")
181         layout.operator("wm.recover_last_session")
182         layout.operator("wm.recover_auto_save", text="Recover Auto Save...")
183
184         layout.separator()
185
186         layout.operator_context = 'EXEC_AREA' if context.blend_data.is_saved else 'INVOKE_AREA'
187         layout.operator("wm.save_mainfile", text="Save", icon='FILE_TICK')
188
189         layout.operator_context = 'INVOKE_AREA'
190         layout.operator("wm.save_as_mainfile", text="Save As...")
191         layout.operator_context = 'INVOKE_AREA'
192         layout.operator("wm.save_as_mainfile", text="Save Copy...").copy = True
193
194         layout.separator()
195         layout.operator_context = 'INVOKE_AREA'
196
197         if any(bpy.utils.app_template_paths()):
198             app_template = context.preferences.app_template
199         else:
200             app_template = None
201
202         if app_template:
203             layout.label(text=bpy.path.display_name(app_template, has_ext=False))
204             layout.operator("wm.save_homefile")
205             layout.operator(
206                 "wm.read_factory_settings",
207                 text="Load Factory Settings",
208             ).app_template = app_template
209         else:
210             layout.operator("wm.save_homefile")
211             layout.operator("wm.read_factory_settings")
212
213         layout.separator()
214
215         layout.operator("preferences.app_template_install", text="Install Application Template...")
216
217         layout.separator()
218
219         layout.operator_context = 'INVOKE_AREA'
220         layout.operator("wm.link", text="Link...", icon='LINK_BLEND')
221         layout.operator("wm.append", text="Append...", icon='APPEND_BLEND')
222         layout.menu("TOPBAR_MT_file_previews")
223
224         layout.separator()
225
226         layout.menu("TOPBAR_MT_file_import", icon='IMPORT')
227         layout.menu("TOPBAR_MT_file_export", icon='EXPORT')
228
229         layout.separator()
230
231         layout.menu("TOPBAR_MT_file_external_data")
232
233         layout.separator()
234
235         layout.operator_context = 'EXEC_AREA'
236         if bpy.data.is_dirty:
237             layout.operator_context = 'INVOKE_SCREEN'  # quit dialog
238         layout.operator("wm.quit_blender", text="Quit", icon='QUIT')
239
240
241 class TOPBAR_MT_file_new(Menu):
242     bl_label = "New File"
243
244     @staticmethod
245     def app_template_paths():
246         import os
247
248         template_paths = bpy.utils.app_template_paths()
249
250         # expand template paths
251         app_templates = []
252         for path in template_paths:
253             for d in os.listdir(path):
254                 if d.startswith(("__", ".")):
255                     continue
256                 template = os.path.join(path, d)
257                 if os.path.isdir(template):
258                     # template_paths_expand.append(template)
259                     app_templates.append(d)
260
261         return sorted(app_templates)
262
263     @staticmethod
264     def draw_ex(layout, _context, *, use_splash=False, use_more=False):
265         layout.operator_context = 'INVOKE_DEFAULT'
266
267         # Limit number of templates in splash screen, spill over into more menu.
268         paths = TOPBAR_MT_file_new.app_template_paths()
269         splash_limit = 5
270
271         if use_splash:
272             icon = 'FILE_NEW'
273             show_more = len(paths) > (splash_limit - 1)
274             if show_more:
275                 paths = paths[:splash_limit - 2]
276         elif use_more:
277             icon = 'FILE_NEW'
278             paths = paths[splash_limit - 2:]
279             show_more = False
280         else:
281             icon = 'NONE'
282             show_more = False
283
284         # Draw application templates.
285         if not use_more:
286             props = layout.operator("wm.read_homefile", text="General", icon=icon)
287             props.app_template = ""
288
289         for d in paths:
290             props = layout.operator(
291                 "wm.read_homefile",
292                 text=bpy.path.display_name(d),
293                 icon=icon,
294             )
295             props.app_template = d
296
297         layout.operator_context = 'EXEC_DEFAULT'
298
299         if show_more:
300             layout.menu("TOPBAR_MT_templates_more", text="...")
301
302     def draw(self, context):
303         TOPBAR_MT_file_new.draw_ex(self.layout, context)
304
305
306 class TOPBAR_MT_templates_more(Menu):
307     bl_label = "Templates"
308
309     def draw(self, context):
310         bpy.types.TOPBAR_MT_file_new.draw_ex(self.layout, context, use_more=True)
311
312
313 class TOPBAR_MT_file_import(Menu):
314     bl_idname = "TOPBAR_MT_file_import"
315     bl_label = "Import"
316
317     def draw(self, _context):
318         if bpy.app.build_options.collada:
319             self.layout.operator("wm.collada_import", text="Collada (Default) (.dae)")
320         if bpy.app.build_options.alembic:
321             self.layout.operator("wm.alembic_import", text="Alembic (.abc)")
322
323
324 class TOPBAR_MT_file_export(Menu):
325     bl_idname = "TOPBAR_MT_file_export"
326     bl_label = "Export"
327
328     def draw(self, _context):
329         if bpy.app.build_options.collada:
330             self.layout.operator("wm.collada_export", text="Collada (Default) (.dae)")
331         if bpy.app.build_options.alembic:
332             self.layout.operator("wm.alembic_export", text="Alembic (.abc)")
333
334
335 class TOPBAR_MT_file_external_data(Menu):
336     bl_label = "External Data"
337
338     def draw(self, _context):
339         layout = self.layout
340
341         icon = 'CHECKBOX_HLT' if bpy.data.use_autopack else 'CHECKBOX_DEHLT'
342         layout.operator("file.autopack_toggle", icon=icon)
343
344         layout.separator()
345
346         pack_all = layout.row()
347         pack_all.operator("file.pack_all")
348         pack_all.active = not bpy.data.use_autopack
349
350         unpack_all = layout.row()
351         unpack_all.operator("file.unpack_all")
352         unpack_all.active = not bpy.data.use_autopack
353
354         layout.separator()
355
356         layout.operator("file.make_paths_relative")
357         layout.operator("file.make_paths_absolute")
358         layout.operator("file.report_missing_files")
359         layout.operator("file.find_missing_files")
360
361
362 class TOPBAR_MT_file_previews(Menu):
363     bl_label = "Data Previews"
364
365     def draw(self, _context):
366         layout = self.layout
367
368         layout.operator("wm.previews_ensure")
369         layout.operator("wm.previews_batch_generate")
370
371         layout.separator()
372
373         layout.operator("wm.previews_clear")
374         layout.operator("wm.previews_batch_clear")
375
376
377 class TOPBAR_MT_render(Menu):
378     bl_label = "Render"
379
380     def draw(self, context):
381         layout = self.layout
382
383         rd = context.scene.render
384
385         layout.operator("render.render", text="Render Image", icon='RENDER_STILL').use_viewport = True
386         props = layout.operator("render.render", text="Render Animation", icon='RENDER_ANIMATION')
387         props.animation = True
388         props.use_viewport = True
389
390         layout.separator()
391
392         layout.operator("sound.mixdown", text="Render Audio...")
393
394         layout.separator()
395
396         layout.operator("render.view_show", text="View Render")
397         layout.operator("render.play_rendered_anim", text="View Animation")
398         layout.prop_menu_enum(rd, "display_mode", text="Display Mode")
399
400         layout.separator()
401
402         layout.prop(rd, "use_lock_interface", text="Lock Interface")
403
404
405 class TOPBAR_MT_edit(Menu):
406     bl_label = "Edit"
407
408     def draw(self, context):
409         layout = self.layout
410
411         layout.operator("ed.undo")
412         layout.operator("ed.redo")
413
414         layout.separator()
415
416         layout.operator("ed.undo_history", text="Undo History...")
417
418         layout.separator()
419
420         layout.operator("screen.repeat_last")
421         layout.operator("screen.repeat_history", text="Repeat History...")
422
423         layout.separator()
424
425         layout.operator("screen.redo_last", text="Adjust Last Operation...")
426
427         layout.separator()
428
429         layout.operator("wm.search_menu", text="Operator Search...", icon='VIEWZOOM')
430
431         layout.separator()
432
433         # Mainly to expose shortcut since this depends on the context.
434         props = layout.operator("wm.call_panel", text="Rename Active Item...", icon='OUTLINER_DATA_FONT')
435         props.name = "TOPBAR_PT_name"
436         props.keep_open = False
437
438         layout.separator()
439
440         # Should move elsewhere (impacts outliner & 3D view).
441         tool_settings = context.tool_settings
442         layout.prop(tool_settings, "lock_object_mode")
443
444         layout.separator()
445
446         layout.operator("screen.userpref_show", text="Preferences...", icon='PREFERENCES')
447
448
449 class TOPBAR_MT_window(Menu):
450     bl_label = "Window"
451
452     def draw(self, context):
453         import sys
454
455         layout = self.layout
456
457         layout.operator("wm.window_new")
458         layout.operator("wm.window_new_main")
459
460         layout.separator()
461
462         layout.operator("wm.window_fullscreen_toggle", icon='FULLSCREEN_ENTER')
463
464         layout.separator()
465
466         layout.operator("screen.workspace_cycle", text="Next Workspace").direction = 'NEXT'
467         layout.operator("screen.workspace_cycle", text="Previous Workspace").direction = 'PREV'
468
469         layout.separator()
470
471         layout.prop(context.screen, "show_statusbar")
472
473         layout.separator()
474
475         layout.operator("screen.screenshot")
476
477         if sys.platform[:3] == "win":
478             layout.separator()
479             layout.operator("wm.console_toggle", icon='CONSOLE')
480
481         if context.scene.render.use_multiview:
482             layout.separator()
483             layout.operator("wm.set_stereo_3d")
484
485
486 class TOPBAR_MT_help(Menu):
487     bl_label = "Help"
488
489     def draw(self, context):
490         # If 'url_prefill_from_blender' becomes slow it could be made into a separate operator
491         # to avoid constructing the bug report just to show this menu.
492         from bl_ui_utils.bug_report_url import url_prefill_from_blender
493
494         layout = self.layout
495
496         show_developer = context.preferences.view.show_developer_ui
497
498         layout.operator(
499             "wm.url_open", text="Manual", icon='HELP',
500         ).url = "https://docs.blender.org/manual/en/dev/"
501
502         layout.operator(
503             "wm.url_open", text="Report a Bug", icon='URL',
504         ).url = url_prefill_from_blender()
505
506         layout.separator()
507
508         layout.operator(
509             "wm.url_open", text="User Communities", icon='URL',
510         ).url = "https://www.blender.org/community/"
511         layout.operator(
512             "wm.url_open", text="Developer Community", icon='URL',
513         ).url = "https://www.blender.org/get-involved/developers/"
514
515         layout.separator()
516
517         layout.operator(
518             "wm.url_open", text="Blender Website", icon='URL',
519         ).url = "https://www.blender.org"
520         layout.operator(
521             "wm.url_open", text="Release Notes", icon='URL',
522         ).url = "https://www.blender.org/download/releases/%d-%d/" % bpy.app.version[:2]
523         layout.operator(
524             "wm.url_open", text="Credits", icon='URL',
525         ).url = "https://www.blender.org/about/credits/"
526
527         layout.separator()
528
529         layout.operator(
530             "wm.url_open", text="Blender Store", icon='URL',
531         ).url = "https://store.blender.org"
532         layout.operator(
533             "wm.url_open", text="Development Fund", icon='URL',
534         ).url = "https://fund.blender.org"
535         layout.operator(
536             "wm.url_open", text="Donate", icon='URL',
537         ).url = "https://www.blender.org/foundation/donation-payment/"
538
539         layout.separator()
540
541         if show_developer:
542             layout.operator(
543                 "wm.url_open", text="Python API Reference", icon='URL',
544             ).url = bpy.types.WM_OT_doc_view._prefix
545
546             layout.operator("wm.operator_cheat_sheet", icon='TEXT')
547
548         layout.operator("wm.sysinfo")
549
550         layout.separator()
551
552         layout.operator("wm.splash", icon='BLENDER')
553
554
555 class TOPBAR_MT_file_context_menu(Menu):
556     bl_label = "File Context Menu"
557
558     def draw(self, _context):
559         layout = self.layout
560
561         layout.operator_context = 'INVOKE_AREA'
562         layout.menu("TOPBAR_MT_file_new", text="New", icon='FILE_NEW')
563         layout.operator("wm.open_mainfile", text="Open...", icon='FILE_FOLDER')
564
565         layout.separator()
566
567         layout.operator("wm.link", text="Link...", icon='LINK_BLEND')
568         layout.operator("wm.append", text="Append...", icon='APPEND_BLEND')
569
570         layout.separator()
571
572         layout.menu("TOPBAR_MT_file_import", icon='IMPORT')
573         layout.menu("TOPBAR_MT_file_export", icon='EXPORT')
574
575         layout.separator()
576
577         layout.operator("screen.userpref_show", text="Preferences...", icon='PREFERENCES')
578
579
580 class TOPBAR_MT_workspace_menu(Menu):
581     bl_label = "Workspace"
582
583     def draw(self, _context):
584         layout = self.layout
585
586         layout.operator("workspace.duplicate", text="Duplicate", icon='DUPLICATE')
587         if len(bpy.data.workspaces) > 1:
588             layout.operator("workspace.delete", text="Delete", icon='REMOVE')
589
590         layout.separator()
591
592         layout.operator("workspace.reorder_to_front", text="Reorder to Front", icon='TRIA_LEFT_BAR')
593         layout.operator("workspace.reorder_to_back", text="Reorder to Back", icon='TRIA_RIGHT_BAR')
594
595         layout.separator()
596
597         # For key binding discoverability.
598         props = layout.operator("screen.workspace_cycle", text="Previous Workspace")
599         props.direction = 'PREV'
600         props = layout.operator("screen.workspace_cycle", text="Next Workspace")
601         props.direction = 'NEXT'
602
603
604 class TOPBAR_PT_active_tool(Panel):
605     bl_space_type = 'PROPERTIES'
606     bl_region_type = 'WINDOW'
607     bl_category = ""
608     bl_context = ".active_tool"  # dot on purpose (access from tool settings)
609     bl_label = "Active Tool"
610     bl_options = {'HIDE_HEADER'}
611
612     def draw(self, context):
613         layout = self.layout
614         tool_mode = context.mode
615
616         # Panel display of topbar tool settings.
617         # currently displays in tool settings, keep here since the same functionality is used for the topbar.
618
619         layout.use_property_split = True
620         layout.use_property_decorate = False
621
622         from .space_toolsystem_common import ToolSelectPanelHelper
623         ToolSelectPanelHelper.draw_active_tool_header(
624             context,
625             layout,
626             show_tool_name=True,
627             tool_key=('VIEW_3D', tool_mode),
628         )
629
630
631 # Grease Pencil Object - Primitive curve
632 class TOPBAR_PT_gpencil_primitive(Panel):
633     bl_space_type = 'VIEW_3D'
634     bl_region_type = 'HEADER'
635     bl_label = "Primitives"
636
637     def draw(self, context):
638         settings = context.tool_settings.gpencil_sculpt
639
640         layout = self.layout
641         # Curve
642         layout.template_curve_mapping(settings, "thickness_primitive_curve", brush=True)
643
644
645 # Grease Pencil Fill
646 class TOPBAR_PT_gpencil_fill(Panel):
647     bl_space_type = 'VIEW_3D'
648     bl_region_type = 'HEADER'
649     bl_label = "Advanced"
650
651     def draw(self, context):
652         paint = context.tool_settings.gpencil_paint
653         brush = paint.brush
654         gp_settings = brush.gpencil_settings
655
656         layout = self.layout
657         # Fill
658         row = layout.row(align=True)
659         row.prop(gp_settings, "fill_factor", text="Resolution")
660         if gp_settings.fill_draw_mode != 'STROKE':
661             row = layout.row(align=True)
662             row.prop(gp_settings, "show_fill", text="Ignore Transparent Strokes")
663             row = layout.row(align=True)
664             row.prop(gp_settings, "fill_threshold", text="Threshold")
665
666
667 # Only a popover
668 class TOPBAR_PT_name(Panel):
669     bl_space_type = 'TOPBAR'  # dummy
670     bl_region_type = 'HEADER'
671     bl_label = "Rename Active Item"
672     bl_ui_units_x = 14
673
674     def draw(self, context):
675         layout = self.layout
676
677         # Edit first editable button in popup
678         def row_with_icon(layout, icon):
679             row = layout.row()
680             row.activate_init = True
681             row.label(icon=icon)
682             return row
683
684         mode = context.mode
685         scene = context.scene
686         space = context.space_data
687         space_type = None if (space is None) else space.type
688         found = False
689         if space_type == 'SEQUENCE_EDITOR':
690             layout.label(text="Sequence Strip Name")
691             item = getattr(scene.sequence_editor, "active_strip")
692             if item:
693                 row = row_with_icon(layout, 'SEQUENCE')
694                 row.prop(item, "name", text="")
695                 found = True
696         elif space_type == 'NODE_EDITOR':
697             layout.label(text="Node Label")
698             item = context.active_node
699             if item:
700                 row = row_with_icon(layout, 'NODE')
701                 row.prop(item, "label", text="")
702                 found = True
703         else:
704             if mode == 'POSE' or (mode == 'WEIGHT_PAINT' and context.pose_object):
705                 layout.label(text="Bone Name")
706                 item = context.active_pose_bone
707                 if item:
708                     row = row_with_icon(layout, 'BONE_DATA')
709                     row.prop(item, "name", text="")
710                     found = True
711             elif mode == 'EDIT_ARMATURE':
712                 layout.label(text="Bone Name")
713                 item = context.active_bone
714                 if item:
715                     row = row_with_icon(layout, 'BONE_DATA')
716                     row.prop(item, "name", text="")
717                     found = True
718             else:
719                 layout.label(text="Object Name")
720                 item = context.object
721                 if item:
722                     row = row_with_icon(layout, 'OBJECT_DATA')
723                     row.prop(item, "name", text="")
724                     found = True
725
726         if not found:
727             row = row_with_icon(layout, 'ERROR')
728             row.label(text="No active item")
729
730
731 classes = (
732     TOPBAR_HT_upper_bar,
733     TOPBAR_MT_file_context_menu,
734     TOPBAR_MT_workspace_menu,
735     TOPBAR_MT_editor_menus,
736     TOPBAR_MT_file,
737     TOPBAR_MT_file_new,
738     TOPBAR_MT_templates_more,
739     TOPBAR_MT_file_import,
740     TOPBAR_MT_file_export,
741     TOPBAR_MT_file_external_data,
742     TOPBAR_MT_file_previews,
743     TOPBAR_MT_edit,
744     TOPBAR_MT_render,
745     TOPBAR_MT_window,
746     TOPBAR_MT_help,
747     TOPBAR_PT_active_tool,
748     TOPBAR_PT_gpencil_layers,
749     TOPBAR_PT_gpencil_primitive,
750     TOPBAR_PT_gpencil_fill,
751     TOPBAR_PT_name,
752 )
753
754 if __name__ == "__main__":  # only for live edit.
755     from bpy.utils import register_class
756     for cls in classes:
757         register_class(cls)