Files
blender/release/scripts/startup/bl_ui/space_topbar.py
Campbell Barton d8daeeb930 UI: Avoid redundant text argument to UnifiedPaintPanel methods
Now when the text argument is omitted, use the default name
matching how regular properties work.

Avoids passing in the same name which RNA has,
matches UILayout.prop behavior.

Also use keyword only for optional arguments.
2019-03-12 16:31:02 +11:00

1070 lines
37 KiB
Python

# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
import bpy
from bpy.types import Header, Menu, Panel
from .properties_grease_pencil_common import (
GPENCIL_UL_layer,
)
class TOPBAR_HT_upper_bar(Header):
bl_space_type = 'TOPBAR'
def draw(self, context):
region = context.region
if region.alignment == 'RIGHT':
self.draw_right(context)
else:
self.draw_left(context)
def draw_left(self, context):
layout = self.layout
window = context.window
screen = context.screen
layout.operator("wm.splash", text="", icon='BLENDER', emboss=False)
TOPBAR_MT_editor_menus.draw_collapsible(context, layout)
layout.separator()
if not screen.show_fullscreen:
layout.template_ID_tabs(
window, "workspace",
new="workspace.add",
menu="TOPBAR_MT_workspace_menu",
)
else:
layout.operator(
"screen.back_to_previous",
icon='SCREEN_BACK',
text="Back to Previous",
)
def draw_right(self, context):
layout = self.layout
window = context.window
screen = context.screen
scene = window.scene
# If statusbar is hidden, still show messages at the top
if not screen.show_statusbar:
layout.template_reports_banner()
layout.template_running_jobs()
# Active workspace view-layer is retrieved through window, not through workspace.
layout.template_ID(window, "scene", new="scene.new", unlink="scene.delete")
row = layout.row(align=True)
row.template_search(
window, "view_layer",
scene, "view_layers",
new="scene.view_layer_add",
unlink="scene.view_layer_remove")
class TOPBAR_HT_lower_bar(Header):
bl_space_type = 'TOPBAR'
bl_region_type = 'WINDOW'
def draw(self, context):
region = context.region
if region.alignment == 'LEFT':
self.draw_left(context)
elif region.alignment == 'RIGHT':
self.draw_right(context)
else:
self.draw_center(context)
def draw_left(self, context):
layout = self.layout
# Active Tool
# -----------
from .space_toolsystem_common import ToolSelectPanelHelper
tool = ToolSelectPanelHelper.draw_active_tool_header(context, layout)
tool_space_type = 'VIEW_3D' if tool is None else tool.space_type
tool_mode = context.mode if tool is None else tool.mode
# Object Mode Options
# -------------------
# Example of how tool_settings can be accessed as pop-overs.
# TODO(campbell): editing options should be after active tool options
# (obviously separated for from the users POV)
draw_fn = getattr(getattr(_draw_left_context_mode, tool_space_type, None), tool_mode, None)
if draw_fn is not None:
draw_fn(context, layout, tool)
if tool_space_type == 'VIEW_3D':
# Note: general mode options should be added to 'draw_right'.
if tool_mode == 'SCULPT':
if (tool is not None) and tool.has_datablock:
layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".paint_common", category="")
elif tool_mode == 'PAINT_VERTEX':
if (tool is not None) and tool.has_datablock:
layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".paint_common", category="")
elif tool_mode == 'PAINT_WEIGHT':
if (tool is not None) and tool.has_datablock:
layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".paint_common", category="")
elif tool_mode == 'PAINT_TEXTURE':
if (tool is not None) and tool.has_datablock:
layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".paint_common", category="")
elif tool_mode == 'EDIT_ARMATURE':
pass
elif tool_mode == 'EDIT_CURVE':
pass
elif tool_mode == 'EDIT_MESH':
pass
elif tool_mode == 'POSE':
pass
elif tool_mode == 'PARTICLE':
# Disable, only shows "Brush" panel, which is already in the top-bar.
# if tool.has_datablock:
# layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".paint_common", category="")
pass
elif tool_mode == 'PAINT_GPENCIL':
if (tool is not None) and tool.has_datablock:
layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".greasepencil_paint", category="")
elif tool_mode == 'SCULPT_GPENCIL':
layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".greasepencil_sculpt", category="")
elif tool_mode == 'WEIGHT_GPENCIL':
layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".greasepencil_weight", category="")
elif tool_space_type == 'IMAGE_EDITOR':
if tool_mode == 'PAINT':
if (tool is not None) and tool.has_datablock:
layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".paint_common_2d", category="")
elif context.uv_sculpt_object is not None:
layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".uv_sculpt", category="")
def draw_center(self, context):
pass
def draw_right(self, context):
layout = self.layout
# Active Tool
# -----------
from .space_toolsystem_common import ToolSelectPanelHelper
tool = ToolSelectPanelHelper.tool_active_from_context(context)
tool_space_type = 'VIEW_3D' if tool is None else tool.space_type
tool_mode = context.mode if tool is None else tool.mode
if tool_space_type == 'VIEW_3D':
if tool_mode == 'SCULPT':
layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".sculpt_mode", category="")
elif tool_mode == 'PAINT_VERTEX':
layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".vertexpaint", category="")
elif tool_mode == 'PAINT_WEIGHT':
layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".weightpaint", category="")
elif tool_mode == 'PAINT_TEXTURE':
layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".imagepaint", category="")
elif tool_mode == 'EDIT_TEXT':
layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".text_edit", category="")
elif tool_mode == 'EDIT_ARMATURE':
layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".armature_edit", category="")
elif tool_mode == 'EDIT_METABALL':
layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".mball_edit", category="")
elif tool_mode == 'EDIT_LATTICE':
layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".lattice_edit", category="")
elif tool_mode == 'EDIT_CURVE':
layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".curve_edit", category="")
elif tool_mode == 'EDIT_MESH':
layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".mesh_edit", category="")
elif tool_mode == 'POSE':
layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".posemode", category="")
elif tool_mode == 'PARTICLE':
layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".particlemode", category="")
elif tool_mode == 'OBJECT':
layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".objectmode", category="")
elif tool_mode in {'PAINT_GPENCIL', 'EDIT_GPENCIL', 'SCULPT_GPENCIL', 'WEIGHT_GPENCIL'}:
# Grease pencil layer.
gpl = context.active_gpencil_layer
if gpl and gpl.info is not None:
text = gpl.info
maxw = 25
if len(text) > maxw:
text = text[:maxw - 5] + '..' + text[-3:]
else:
text = ""
layout.label(text="Layer:")
sub = layout.row()
sub.ui_units_x = 8
sub.popover(
panel="TOPBAR_PT_gpencil_layers",
text=text,
)
elif tool_space_type == 'IMAGE_EDITOR':
if tool_mode == 'PAINT':
layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".imagepaint_2d", category="")
class _draw_left_context_mode:
class VIEW_3D:
@staticmethod
def SCULPT(context, layout, tool):
if (tool is None) or (not tool.has_datablock):
return
paint = context.tool_settings.sculpt
layout.template_ID_preview(paint, "brush", rows=3, cols=8, hide_buttons=True)
brush = paint.brush
if brush is None:
return
from .properties_paint_common import (
brush_basic_sculpt_settings,
)
brush_basic_sculpt_settings(layout, context, brush, compact=True)
@staticmethod
def PAINT_TEXTURE(context, layout, tool):
if (tool is None) or (not tool.has_datablock):
return
paint = context.tool_settings.image_paint
layout.template_ID_preview(paint, "brush", rows=3, cols=8, hide_buttons=True)
brush = paint.brush
if brush is None:
return
from .properties_paint_common import (
UnifiedPaintPanel,
brush_basic_texpaint_settings,
)
capabilities = brush.image_paint_capabilities
if capabilities.has_color:
UnifiedPaintPanel.prop_unified_color(layout, context, brush, "color", text="")
brush_basic_texpaint_settings(layout, context, brush, compact=True)
@staticmethod
def PAINT_VERTEX(context, layout, tool):
if (tool is None) or (not tool.has_datablock):
return
paint = context.tool_settings.vertex_paint
layout.template_ID_preview(paint, "brush", rows=3, cols=8, hide_buttons=True)
brush = paint.brush
if brush is None:
return
from .properties_paint_common import (
UnifiedPaintPanel,
brush_basic_vpaint_settings,
)
capabilities = brush.vertex_paint_capabilities
if capabilities.has_color:
UnifiedPaintPanel.prop_unified_color(layout, context, brush, "color", text="")
brush_basic_vpaint_settings(layout, context, brush, compact=True)
@staticmethod
def PAINT_WEIGHT(context, layout, tool):
if (tool is None) or (not tool.has_datablock):
return
paint = context.tool_settings.weight_paint
layout.template_ID_preview(paint, "brush", rows=3, cols=8, hide_buttons=True)
brush = paint.brush
if brush is None:
return
from .properties_paint_common import brush_basic_wpaint_settings
brush_basic_wpaint_settings(layout, context, brush, compact=True)
@staticmethod
def PAINT_GPENCIL(context, layout, tool):
if tool is None:
return
is_paint = True
if tool.name in {"Line", "Box", "Circle", "Arc", "Curve"}:
is_paint = False
elif tool.name == "Cutter":
row = layout.row(align=True)
row.prop(context.tool_settings.gpencil_sculpt, "intersection_threshold")
return
elif not tool.has_datablock:
return
paint = context.tool_settings.gpencil_paint
brush = paint.brush
if brush is None:
return
gp_settings = brush.gpencil_settings
def draw_color_selector():
ma = gp_settings.material
row = layout.row(align=True)
icon_id = 0
if ma:
icon_id = ma.id_data.preview.icon_id
txt_ma = ma.name
maxw = 25
if len(txt_ma) > maxw:
txt_ma = txt_ma[:maxw - 5] + '..' + txt_ma[-3:]
else:
txt_ma = ""
row.label(text="Material:")
sub = row.row()
sub.ui_units_x = 8
sub.popover(
panel="TOPBAR_PT_gpencil_materials",
text=txt_ma,
icon_value=icon_id,
)
row.prop(gp_settings, "use_material_pin", text="")
row = layout.row(align=True)
tool_settings = context.scene.tool_settings
settings = tool_settings.gpencil_paint
row.template_ID_preview(settings, "brush", rows=3, cols=8, hide_buttons=True)
if brush.gpencil_tool in {'FILL', 'DRAW'}:
draw_color_selector()
from .properties_paint_common import (
brush_basic_gpencil_paint_settings,
)
brush_basic_gpencil_paint_settings(layout, context, brush, compact=True)
if tool.name in {"Arc", "Curve", "Line", "Box", "Circle"}:
settings = context.tool_settings.gpencil_sculpt
row = layout.row(align=True)
row.prop(settings, "use_thickness_curve", text="", icon='CURVE_DATA')
sub = row.row(align=True)
sub.active = settings.use_thickness_curve
sub.popover(
panel="TOPBAR_PT_gpencil_primitive",
text="Thickness Profile"
)
@staticmethod
def SCULPT_GPENCIL(context, layout, tool):
if (tool is None) or (not tool.has_datablock):
return
tool_settings = context.tool_settings
settings = tool_settings.gpencil_sculpt
brush = settings.brush
from .properties_paint_common import (
brush_basic_gpencil_sculpt_settings,
)
brush_basic_gpencil_sculpt_settings(layout, context, brush, compact=True)
@staticmethod
def WEIGHT_GPENCIL(context, layout, tool):
if (tool is None) or (not tool.has_datablock):
return
tool_settings = context.tool_settings
settings = tool_settings.gpencil_sculpt
brush = settings.brush
from .properties_paint_common import (
brush_basic_gpencil_weight_settings,
)
brush_basic_gpencil_weight_settings(layout, context, brush, compact=True)
@staticmethod
def PARTICLE(context, layout, tool):
if (tool is None) or (not tool.has_datablock):
return
# See: 'VIEW3D_PT_tools_brush', basically a duplicate
settings = context.tool_settings.particle_edit
brush = settings.brush
tool = settings.tool
if tool != 'NONE':
layout.prop(brush, "size", slider=True)
if tool == 'ADD':
layout.prop(brush, "count")
layout.prop(settings, "use_default_interpolate")
layout.prop(brush, "steps", slider=True)
layout.prop(settings, "default_key_count", slider=True)
else:
layout.prop(brush, "strength", slider=True)
if tool == 'LENGTH':
layout.row().prop(brush, "length_mode", expand=True)
elif tool == 'PUFF':
layout.row().prop(brush, "puff_mode", expand=True)
layout.prop(brush, "use_puff_volume")
elif tool == 'COMB':
# Note: actually in 'Options' panel,
# disabled when used in popover.
row = layout.row()
row.active = settings.is_editable
row.prop(settings, "use_emitter_deflect", text="Deflect Emitter")
sub = row.row(align=True)
sub.active = settings.use_emitter_deflect
sub.prop(settings, "emitter_distance", text="Distance")
class IMAGE_EDITOR:
@staticmethod
def VIEW(context, layout, tool):
tool_settings = context.tool_settings
if tool_settings.use_uv_sculpt:
if context.mode == 'EDIT_MESH':
uv_sculpt = tool_settings.uv_sculpt
brush = uv_sculpt.brush
if brush:
from .properties_paint_common import UnifiedPaintPanel
row = layout.row(align=True)
UnifiedPaintPanel.prop_unified_size(row, context, brush, "size", slider=True)
UnifiedPaintPanel.prop_unified_size(row, context, brush, "use_pressure_size", text="")
row = layout.row(align=True)
UnifiedPaintPanel.prop_unified_strength(row, context, brush, "strength", slider=True)
UnifiedPaintPanel.prop_unified_strength(row, context, brush, "use_pressure_strength", text="")
@staticmethod
def PAINT(context, layout, tool):
if (tool is None) or (not tool.has_datablock):
return
paint = context.tool_settings.image_paint
layout.template_ID_preview(paint, "brush", rows=3, cols=8, hide_buttons=True)
brush = paint.brush
if brush is None:
return
from .properties_paint_common import (
UnifiedPaintPanel,
brush_basic_texpaint_settings,
)
capabilities = brush.image_paint_capabilities
if capabilities.has_color:
UnifiedPaintPanel.prop_unified_color(layout, context, brush, "color", text="")
brush_basic_texpaint_settings(layout, context, brush, compact=True)
class TOPBAR_PT_gpencil_layers(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'HEADER'
bl_label = "Layers"
bl_ui_units_x = 14
@classmethod
def poll(cls, context):
if context.gpencil_data is None:
return False
ob = context.object
if ob is not None and ob.type == 'GPENCIL':
return True
return False
@staticmethod
def draw(self, context):
layout = self.layout
gpd = context.gpencil_data
# Grease Pencil data...
if (gpd is None) or (not gpd.layers):
layout.operator("gpencil.layer_add", text="New Layer")
else:
self.draw_layers(context, layout, gpd)
def draw_layers(self, context, layout, gpd):
row = layout.row()
col = row.column()
layer_rows = 10
col.template_list("GPENCIL_UL_layer", "", gpd, "layers", gpd.layers, "active_index",
rows=layer_rows, sort_reverse=True, sort_lock=True)
gpl = context.active_gpencil_layer
if gpl:
srow = col.row(align=True)
srow.prop(gpl, "blend_mode", text="Blend")
srow = col.row(align=True)
srow.prop(gpl, "opacity", text="Opacity", slider=True)
srow.prop(gpl, "clamp_layer", text="",
icon='MOD_MASK' if gpl.clamp_layer else 'LAYER_ACTIVE')
srow = col.row(align=True)
srow.prop(gpl, "use_solo_mode", text="Show Only On Keyframed")
col = row.column()
sub = col.column(align=True)
sub.operator("gpencil.layer_add", icon='ADD', text="")
sub.operator("gpencil.layer_remove", icon='REMOVE', text="")
gpl = context.active_gpencil_layer
if gpl:
sub.menu("GPENCIL_MT_layer_context_menu", icon='DOWNARROW_HLT', text="")
if len(gpd.layers) > 1:
col.separator()
sub = col.column(align=True)
sub.operator("gpencil.layer_move", icon='TRIA_UP', text="").type = 'UP'
sub.operator("gpencil.layer_move", icon='TRIA_DOWN', text="").type = 'DOWN'
col.separator()
sub = col.column(align=True)
sub.operator("gpencil.layer_isolate", icon='LOCKED', text="").affect_visibility = False
sub.operator("gpencil.layer_isolate", icon='HIDE_OFF', text="").affect_visibility = True
class TOPBAR_MT_editor_menus(Menu):
bl_idname = "TOPBAR_MT_editor_menus"
bl_label = ""
def draw(self, context):
layout = self.layout
layout.menu("TOPBAR_MT_file")
layout.menu("TOPBAR_MT_edit")
layout.menu("TOPBAR_MT_render")
layout.menu("TOPBAR_MT_window")
layout.menu("TOPBAR_MT_help")
class TOPBAR_MT_file(Menu):
bl_label = "File"
def draw(self, context):
layout = self.layout
layout.operator_context = 'INVOKE_AREA'
layout.menu("TOPBAR_MT_file_new", text="New", icon='FILE_NEW')
layout.operator("wm.open_mainfile", text="Open...", icon='FILE_FOLDER')
layout.menu("TOPBAR_MT_file_open_recent")
layout.operator("wm.revert_mainfile")
layout.operator("wm.recover_last_session")
layout.operator("wm.recover_auto_save", text="Recover Auto Save...")
layout.separator()
layout.operator_context = 'EXEC_AREA' if context.blend_data.is_saved else 'INVOKE_AREA'
layout.operator("wm.save_mainfile", text="Save", icon='FILE_TICK')
layout.operator_context = 'INVOKE_AREA'
layout.operator("wm.save_as_mainfile", text="Save As...")
layout.operator_context = 'INVOKE_AREA'
layout.operator("wm.save_as_mainfile", text="Save Copy...").copy = True
layout.separator()
layout.operator_context = 'INVOKE_AREA'
if any(bpy.utils.app_template_paths()):
app_template = context.preferences.app_template
else:
app_template = None
if app_template:
layout.label(text=bpy.path.display_name(app_template, has_ext=False))
layout.operator("wm.save_homefile")
layout.operator(
"wm.read_factory_settings",
text="Load Factory Settings",
).app_template = app_template
else:
layout.operator("wm.save_homefile")
layout.operator("wm.read_factory_settings")
layout.separator()
layout.operator("preferences.app_template_install", text="Install Application Template...")
layout.separator()
layout.operator_context = 'INVOKE_AREA'
layout.operator("wm.link", text="Link...", icon='LINK_BLEND')
layout.operator("wm.append", text="Append...", icon='APPEND_BLEND')
layout.menu("TOPBAR_MT_file_previews")
layout.separator()
layout.menu("TOPBAR_MT_file_import", icon='IMPORT')
layout.menu("TOPBAR_MT_file_export", icon='EXPORT')
layout.separator()
layout.menu("TOPBAR_MT_file_external_data")
layout.separator()
layout.operator_context = 'EXEC_AREA'
if bpy.data.is_dirty:
layout.operator_context = 'INVOKE_SCREEN' # quit dialog
layout.operator("wm.quit_blender", text="Quit", icon='QUIT')
class TOPBAR_MT_file_new(Menu):
bl_label = "New File"
@staticmethod
def app_template_paths():
import os
template_paths = bpy.utils.app_template_paths()
# expand template paths
app_templates = []
for path in template_paths:
for d in os.listdir(path):
if d.startswith(("__", ".")):
continue
template = os.path.join(path, d)
if os.path.isdir(template):
# template_paths_expand.append(template)
app_templates.append(d)
return sorted(app_templates)
def draw_ex(layout, context, *, use_splash=False, use_more=False):
layout.operator_context = 'EXEC_DEFAULT'
# Limit number of templates in splash screen, spill over into more menu.
paths = TOPBAR_MT_file_new.app_template_paths()
splash_limit = 5
if use_splash:
icon = 'FILE_NEW'
show_more = len(paths) > (splash_limit - 1)
if show_more:
paths = paths[:splash_limit - 2]
elif use_more:
icon = 'FILE_NEW'
paths = paths[splash_limit - 2:]
show_more = False
else:
icon = 'NONE'
show_more = False
# Draw application templates.
if not use_more:
props = layout.operator("wm.read_homefile", text="General", icon=icon)
props.app_template = ""
for d in paths:
props = layout.operator(
"wm.read_homefile",
text=bpy.path.display_name(d),
icon=icon,
)
props.app_template = d
if show_more:
layout.menu("TOPBAR_MT_templates_more", text="...")
def draw(self, context):
TOPBAR_MT_file_new.draw_ex(self.layout, context)
class TOPBAR_MT_templates_more(Menu):
bl_label = "Templates"
def draw(self, context):
bpy.types.TOPBAR_MT_file_new.draw_ex(self.layout, context, use_more=True)
class TOPBAR_MT_file_import(Menu):
bl_idname = "TOPBAR_MT_file_import"
bl_label = "Import"
def draw(self, context):
if bpy.app.build_options.collada:
self.layout.operator("wm.collada_import", text="Collada (Default) (.dae)")
if bpy.app.build_options.alembic:
self.layout.operator("wm.alembic_import", text="Alembic (.abc)")
class TOPBAR_MT_file_export(Menu):
bl_idname = "TOPBAR_MT_file_export"
bl_label = "Export"
def draw(self, context):
if bpy.app.build_options.collada:
self.layout.operator("wm.collada_export", text="Collada (Default) (.dae)")
if bpy.app.build_options.alembic:
self.layout.operator("wm.alembic_export", text="Alembic (.abc)")
class TOPBAR_MT_file_external_data(Menu):
bl_label = "External Data"
def draw(self, context):
layout = self.layout
icon = 'CHECKBOX_HLT' if bpy.data.use_autopack else 'CHECKBOX_DEHLT'
layout.operator("file.autopack_toggle", icon=icon)
layout.separator()
pack_all = layout.row()
pack_all.operator("file.pack_all")
pack_all.active = not bpy.data.use_autopack
unpack_all = layout.row()
unpack_all.operator("file.unpack_all")
unpack_all.active = not bpy.data.use_autopack
layout.separator()
layout.operator("file.make_paths_relative")
layout.operator("file.make_paths_absolute")
layout.operator("file.report_missing_files")
layout.operator("file.find_missing_files")
class TOPBAR_MT_file_previews(Menu):
bl_label = "Data Previews"
def draw(self, context):
layout = self.layout
layout.operator("wm.previews_ensure")
layout.operator("wm.previews_batch_generate")
layout.separator()
layout.operator("wm.previews_clear")
layout.operator("wm.previews_batch_clear")
class TOPBAR_MT_render(Menu):
bl_label = "Render"
def draw(self, context):
layout = self.layout
rd = context.scene.render
layout.operator("render.render", text="Render Image", icon='RENDER_STILL').use_viewport = True
props = layout.operator("render.render", text="Render Animation", icon='RENDER_ANIMATION')
props.animation = True
props.use_viewport = True
layout.separator()
layout.operator("sound.mixdown", text="Render Audio...")
layout.separator()
layout.operator("render.view_show", text="View Render")
layout.operator("render.play_rendered_anim", text="View Animation")
layout.prop_menu_enum(rd, "display_mode", text="Display Mode")
layout.separator()
layout.prop(rd, "use_lock_interface", text="Lock Interface")
class TOPBAR_MT_edit(Menu):
bl_label = "Edit"
def draw(self, context):
layout = self.layout
layout.operator("ed.undo")
layout.operator("ed.redo")
layout.separator()
layout.operator("ed.undo_history", text="Undo History...")
layout.separator()
layout.operator("screen.repeat_last")
layout.operator("screen.repeat_history", text="Repeat History...")
layout.separator()
layout.operator("screen.redo_last", text="Adjust Last Operation...")
layout.separator()
layout.operator("wm.search_menu", text="Operator Search...", icon='VIEWZOOM')
layout.separator()
# Should move elsewhere (impacts outliner & 3D view).
tool_settings = context.tool_settings
layout.prop(tool_settings, "lock_object_mode")
layout.separator()
layout.operator("screen.userpref_show", text="Preferences...", icon='PREFERENCES')
class TOPBAR_MT_window(Menu):
bl_label = "Window"
def draw(self, context):
import sys
layout = self.layout
layout.operator("wm.window_new")
layout.operator("wm.window_new_main")
layout.separator()
layout.operator("wm.window_fullscreen_toggle", icon='FULLSCREEN_ENTER')
layout.separator()
layout.operator("screen.workspace_cycle", text="Next Workspace").direction = 'NEXT'
layout.operator("screen.workspace_cycle", text="Previous Workspace").direction = 'PREV'
layout.separator()
layout.prop(context.screen, "show_topbar")
layout.prop(context.screen, "show_statusbar")
layout.separator()
layout.operator("screen.screenshot")
if sys.platform[:3] == "win":
layout.separator()
layout.operator("wm.console_toggle", icon='CONSOLE')
if context.scene.render.use_multiview:
layout.separator()
layout.operator("wm.set_stereo_3d")
class TOPBAR_MT_help(Menu):
bl_label = "Help"
def draw(self, context):
layout = self.layout
show_developer = context.preferences.view.show_developer_ui
layout.operator(
"wm.url_open", text="Manual", icon='HELP',
).url = "https://docs.blender.org/manual/en/dev/"
layout.operator(
"wm.url_open", text="Report a Bug", icon='URL',
).url = "https://developer.blender.org/maniphest/task/edit/form/1"
layout.separator()
layout.operator(
"wm.url_open", text="User Communities", icon='URL',
).url = "https://www.blender.org/community/"
layout.operator(
"wm.url_open", text="Developer Community", icon='URL',
).url = "https://www.blender.org/get-involved/developers/"
layout.separator()
layout.operator(
"wm.url_open", text="Blender Website", icon='URL',
).url = "https://www.blender.org"
layout.operator(
"wm.url_open", text="Release Notes", icon='URL',
).url = "https://www.blender.org/download/releases/%d-%d/" % bpy.app.version[:2]
layout.operator(
"wm.url_open", text="Credits", icon='URL',
).url = "https://www.blender.org/about/credits/"
layout.separator()
layout.operator(
"wm.url_open", text="Blender Store", icon='URL',
).url = "https://store.blender.org"
layout.operator(
"wm.url_open", text="Development Fund", icon='URL'
).url = "https://fund.blender.org"
layout.operator(
"wm.url_open", text="Donate", icon='URL',
).url = "https://www.blender.org/foundation/donation-payment/"
layout.separator()
if show_developer:
layout.operator(
"wm.url_open", text="Python API Reference", icon='URL',
).url = bpy.types.WM_OT_doc_view._prefix
layout.operator("wm.operator_cheat_sheet", icon='TEXT')
layout.operator("wm.sysinfo")
layout.separator()
layout.operator("wm.splash", icon='BLENDER')
class TOPBAR_MT_file_context_menu(Menu):
bl_label = "File Context Menu"
def draw(self, context):
layout = self.layout
layout.operator_context = 'INVOKE_AREA'
layout.operator("wm.read_homefile", text="New", icon='FILE_NEW')
layout.operator("wm.open_mainfile", text="Open...", icon='FILE_FOLDER')
layout.separator()
layout.operator("wm.link", text="Link...", icon='LINK_BLEND')
layout.operator("wm.append", text="Append...", icon='APPEND_BLEND')
layout.separator()
layout.menu("TOPBAR_MT_file_import", icon='IMPORT')
layout.menu("TOPBAR_MT_file_export", icon='EXPORT')
class TOPBAR_MT_window_context_menu(Menu):
bl_label = "Window Context Menu"
def draw(self, context):
layout = self.layout
layout.operator_context = 'EXEC_AREA'
layout.operator("wm.window_new")
layout.operator("wm.window_new_main")
layout.operator_context = 'INVOKE_AREA'
layout.operator("screen.area_dupli", icon='DUPLICATE')
layout.separator()
layout.operator("screen.area_split", text="Horizontal Split").direction = 'HORIZONTAL'
layout.operator("screen.area_split", text="Vertical Split").direction = 'VERTICAL'
layout.separator()
layout.operator("wm.window_fullscreen_toggle", icon='FULLSCREEN_ENTER')
layout.separator()
layout.operator("screen.userpref_show", text="Preferences...", icon='PREFERENCES')
class TOPBAR_MT_workspace_menu(Menu):
bl_label = "Workspace"
def draw(self, context):
layout = self.layout
layout.operator("workspace.duplicate", text="Duplicate", icon='DUPLICATE')
if len(bpy.data.workspaces) > 1:
layout.operator("workspace.delete", text="Delete", icon='REMOVE')
layout.separator()
layout.operator("workspace.reorder_to_front", text="Reorder to Front", icon='TRIA_LEFT_BAR')
layout.operator("workspace.reorder_to_back", text="Reorder to Back", icon='TRIA_RIGHT_BAR')
layout.separator()
# For key binding discoverability.
props = layout.operator("screen.workspace_cycle", text="Previous Workspace")
props.direction = 'PREV'
props = layout.operator("screen.workspace_cycle", text="Next Workspace")
props.direction = 'NEXT'
class TOPBAR_PT_active_tool(Panel):
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_category = ""
bl_context = ".active_tool" # dot on purpose (access from tool settings)
bl_label = "Active Tool"
bl_options = {'HIDE_HEADER'}
def draw(self, context):
layout = self.layout
# Panel display of topbar tool settings.
# currently displays in tool settings, keep here since the same functionality is used for the topbar.
layout.use_property_split = True
layout.use_property_decorate = False
from .space_toolsystem_common import ToolSelectPanelHelper
ToolSelectPanelHelper.draw_active_tool_header(context, layout, show_tool_name=True)
# Grease Pencil Object - Primitive curve
class TOPBAR_PT_gpencil_primitive(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'HEADER'
bl_label = "Primitives"
@staticmethod
def draw(self, context):
settings = context.tool_settings.gpencil_sculpt
layout = self.layout
# Curve
layout.template_curve_mapping(settings, "thickness_primitive_curve", brush=True)
classes = (
TOPBAR_HT_upper_bar,
TOPBAR_HT_lower_bar,
TOPBAR_MT_file_context_menu,
TOPBAR_MT_window_context_menu,
TOPBAR_MT_workspace_menu,
TOPBAR_MT_editor_menus,
TOPBAR_MT_file,
TOPBAR_MT_file_new,
TOPBAR_MT_templates_more,
TOPBAR_MT_file_import,
TOPBAR_MT_file_export,
TOPBAR_MT_file_external_data,
TOPBAR_MT_file_previews,
TOPBAR_MT_edit,
TOPBAR_MT_render,
TOPBAR_MT_window,
TOPBAR_MT_help,
TOPBAR_PT_active_tool,
TOPBAR_PT_gpencil_layers,
TOPBAR_PT_gpencil_primitive,
)
if __name__ == "__main__": # only for live edit.
from bpy.utils import register_class
for cls in classes:
register_class(cls)