diff options
author | Campbell Barton <ideasman42@gmail.com> | 2019-04-18 22:13:22 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2019-04-19 07:53:38 +0300 |
commit | 9573bf432c4b06d940b4b38cc455826f47518884 (patch) | |
tree | 6e8d4136abfbbd953423b1b6948ab64f11187eee | |
parent | 638938e5a8c30c405c3b4e96ab4f78095003958b (diff) |
UI: move top-bar into the spaces header
Currently this is only in the 3D viewport however all spaces
that use the tool-system will have this region added.
D4680 by @brecht with own updates.
21 files changed, 812 insertions, 549 deletions
diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py index 7d3b76683e9..ef360499535 100644 --- a/release/scripts/startup/bl_ui/space_image.py +++ b/release/scripts/startup/bl_ui/space_image.py @@ -506,6 +506,128 @@ class IMAGE_MT_uvs_snap_pie(Menu): pie.operator("uv.snap_selected", text="Selected to Adjacent Unselected", icon='RESTRICT_SELECT_OFF').target = 'ADJACENT_UNSELECTED' +class IMAGE_HT_tool_header(Header): + bl_space_type = 'IMAGE_EDITOR' + bl_region_type = "TOOL_HEADER" + + def draw(self, context): + layout = self.layout + + layout.row(align=True).template_header() + + self.draw_tool_settings(context) + + sima = context.space_data + show_uvedit = sima.show_uvedit + show_maskedit = sima.show_maskedit + + layout.separator_spacer() + + if show_uvedit or show_maskedit: + layout.prop(sima, "pivot_point", icon_only=True) + + if show_uvedit: + tool_settings = context.tool_settings + + # Snap. + row = layout.row(align=True) + row.prop(tool_settings, "use_snap", text="") + row.prop(tool_settings, "snap_uv_element", icon_only=True) + if tool_settings.snap_uv_element != 'INCREMENT': + row.prop(tool_settings, "snap_target", text="") + + # Proportional Editing + row = layout.row(align=True) + row.prop(tool_settings, "proportional_edit", icon_only=True) + # if tool_settings.proportional_edit != 'DISABLED': + sub = row.row(align=True) + sub.active = tool_settings.proportional_edit != 'DISABLED' + sub.prop(tool_settings, "proportional_edit_falloff", icon_only=True) + + layout.separator_spacer() + + self.draw_mode_settings(context) + + def draw_tool_settings(self, context): + layout = self.layout + + # Active Tool + # ----------- + from .space_toolsystem_common import ToolSelectPanelHelper + tool = ToolSelectPanelHelper.draw_active_tool_header(context, layout) + 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(_draw_tool_settings_context_mode, tool_mode, None) + if draw_fn is not None: + draw_fn(context, layout, tool) + + 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_mode_settings(self, context): + layout = self.layout + + # Active Tool + # ----------- + from .space_toolsystem_common import ToolSelectPanelHelper + tool = ToolSelectPanelHelper.tool_active_from_context(context) + tool_mode = context.mode if tool is None else tool.mode + + if tool_mode == 'PAINT': + layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".imagepaint_2d", category="") + + +class _draw_tool_settings_context_mode: + @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 IMAGE_HT_header(Header): bl_space_type = 'IMAGE_EDITOR' @@ -521,8 +643,8 @@ class IMAGE_HT_header(Header): show_uvedit = sima.show_uvedit show_maskedit = sima.show_maskedit - row = layout.row(align=True) - row.template_header() + if not sima.show_region_tool_header: + layout.row(align=True).template_header() if sima.mode != 'UV': layout.prop(sima, "ui_mode", text="") @@ -560,25 +682,6 @@ class IMAGE_HT_header(Header): mesh = context.edit_object.data layout.prop_search(mesh.uv_layers, "active", mesh, "uv_layers", text="") - if show_uvedit or show_maskedit: - layout.prop(sima, "pivot_point", icon_only=True) - - if show_uvedit: - # Snap. - row = layout.row(align=True) - row.prop(tool_settings, "use_snap", text="") - row.prop(tool_settings, "snap_uv_element", icon_only=True) - if tool_settings.snap_uv_element != 'INCREMENT': - row.prop(tool_settings, "snap_target", text="") - - # Proportional Editing - row = layout.row(align=True) - row.prop(tool_settings, "proportional_edit", icon_only=True) - # if tool_settings.proportional_edit != 'DISABLED': - sub = row.row(align=True) - sub.active = tool_settings.proportional_edit != 'DISABLED' - sub.prop(tool_settings, "proportional_edit_falloff", icon_only=True) - row = layout.row() row.popover( panel="IMAGE_PT_view_display", @@ -1494,6 +1597,7 @@ classes = ( IMAGE_MT_uvs_context_menu, IMAGE_MT_pivot_pie, IMAGE_MT_uvs_snap_pie, + IMAGE_HT_tool_header, IMAGE_HT_header, MASK_MT_editor_menus, IMAGE_PT_mask, diff --git a/release/scripts/startup/bl_ui/space_topbar.py b/release/scripts/startup/bl_ui/space_topbar.py index 7598c6954d5..04908eeb996 100644 --- a/release/scripts/startup/bl_ui/space_topbar.py +++ b/release/scripts/startup/bl_ui/space_topbar.py @@ -80,399 +80,6 @@ class TOPBAR_HT_upper_bar(Header): 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 == 'RIGHT': - self.draw_right(context) - else: - self.draw_left(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_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 - # FIXME: tools must use their own UI drawing! - if tool.idname in {"builtin.line", "builtin.box", "builtin.circle", "builtin.arc", "builtin.curve"}: - # is_paint = False - pass - elif tool.idname == "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) - if not gp_settings.use_material_pin: - ma = context.object.active_material - 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 context.object and 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) - - # FIXME: tools must use their own UI drawing! - if tool.idname in {"builtin.arc", "builtin.curve", "builtin.line", "builtin.box", "builtin.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", - ) - - if brush.gpencil_tool == 'FILL': - settings = context.tool_settings.gpencil_sculpt - row = layout.row(align=True) - sub = row.row(align=True) - sub.popover( - panel="TOPBAR_PT_gpencil_fill", - text="Fill Options", - ) - - @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': - 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' @@ -858,7 +465,6 @@ class TOPBAR_MT_window(Menu): layout.separator() - layout.prop(context.screen, "show_topbar") layout.prop(context.screen, "show_statusbar") layout.separator() @@ -1053,7 +659,7 @@ class TOPBAR_PT_gpencil_fill(Panel): # Only a popover class TOPBAR_PT_name(Panel): bl_space_type = 'TOPBAR' # dummy - bl_region_type = 'WINDOW' + bl_region_type = 'HEADER' bl_label = "Rename Active Item" bl_ui_units_x = 14 @@ -1120,7 +726,6 @@ class TOPBAR_PT_name(Panel): classes = ( TOPBAR_HT_upper_bar, - TOPBAR_HT_lower_bar, TOPBAR_MT_file_context_menu, TOPBAR_MT_workspace_menu, TOPBAR_MT_editor_menus, @@ -1139,7 +744,6 @@ classes = ( TOPBAR_PT_gpencil_layers, TOPBAR_PT_gpencil_primitive, TOPBAR_PT_gpencil_fill, - TOPBAR_PT_name, ) if __name__ == "__main__": # only for live edit. diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index d16a50cc3d1..6cdc7dd725c 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -34,12 +34,15 @@ from .properties_grease_pencil_common import ( from bpy.app.translations import contexts as i18n_contexts -class VIEW3D_HT_header(Header): +class VIEW3D_HT_tool_header(Header): bl_space_type = 'VIEW_3D' + bl_region_type = "TOOL_HEADER" def draw(self, context): layout = self.layout + layout.row(align=True).template_header() + view = context.space_data shading = view.shading # mode_string = context.mode @@ -47,85 +50,13 @@ class VIEW3D_HT_header(Header): overlay = view.overlay tool_settings = context.tool_settings - row = layout.row(align=True) - row.template_header() - object_mode = 'OBJECT' if obj is None else obj.mode has_pose_mode = ( (object_mode == 'POSE') or (object_mode == 'WEIGHT_PAINT' and context.pose_object is not None) ) - # Note: This is actually deadly in case enum_items have to be dynamically generated - # (because internal RNA array iterator will free everything immediately...). - # XXX This is an RNA internal issue, not sure how to fix it. - # Note: Tried to add an accessor to get translated UI strings instead of manual call - # to pgettext_iface below, but this fails because translated enumitems - # are always dynamically allocated. - act_mode_item = bpy.types.Object.bl_rna.properties["mode"].enum_items[object_mode] - act_mode_i18n_context = bpy.types.Object.bl_rna.properties["mode"].translation_context - - row.separator() - - sub = row.row() - sub.ui_units_x = 5.5 - sub.operator_menu_enum("object.mode_set", "mode", - text=bpy.app.translations.pgettext_iface(act_mode_item.name, act_mode_i18n_context), - icon=act_mode_item.icon) - del act_mode_item - - layout.template_header_3D_mode() - - # Contains buttons like Mode, Pivot, Layer, Mesh Select Mode... - if obj: - # Particle edit - if object_mode == 'PARTICLE_EDIT': - row = layout.row() - row.prop(tool_settings.particle_edit, "select_mode", text="", expand=True) - - # Grease Pencil - if obj and obj.type == 'GPENCIL' and context.gpencil_data: - gpd = context.gpencil_data - - if gpd.is_stroke_paint_mode: - row = layout.row() - sub = row.row(align=True) - sub.prop(tool_settings, "use_gpencil_draw_onback", text="", icon='MOD_OPACITY') - sub.separator(factor=0.4) - sub.prop(tool_settings, "use_gpencil_weight_data_add", text="", icon='WPAINT_HLT') - sub.separator(factor=0.4) - sub.prop(tool_settings, "use_gpencil_draw_additive", text="", icon='FREEZE') - - if gpd.use_stroke_edit_mode: - row = layout.row(align=True) - row.prop(tool_settings, "gpencil_selectmode", text="", expand=True) - - if gpd.use_stroke_edit_mode or gpd.is_stroke_sculpt_mode or gpd.is_stroke_weight_mode: - row = layout.row(align=True) - - if gpd.is_stroke_sculpt_mode: - row.prop(tool_settings.gpencil_sculpt, "use_select_mask", text="") - row.separator() - - row.prop(gpd, "use_multiedit", text="", icon='GP_MULTIFRAME_EDITING') - - sub = row.row(align=True) - sub.active = gpd.use_multiedit - sub.popover( - panel="VIEW3D_PT_gpencil_multi_frame", - text="Multiframe", - ) - - if gpd.use_stroke_edit_mode: - row = layout.row(align=True) - row.prop(tool_settings.gpencil_sculpt, "use_select_mask", text="") - - row.popover( - panel="VIEW3D_PT_tools_grease_pencil_interpolate", - text="Interpolate", - ) - - VIEW3D_MT_editor_menus.draw_collapsible(context, layout) + self.draw_tool_settings(context) layout.separator_spacer() @@ -257,6 +188,428 @@ class VIEW3D_HT_header(Header): layout.separator_spacer() + self.draw_mode_settings(context) + + def draw_tool_settings(self, context): + layout = self.layout + + # Active Tool + # ----------- + from .space_toolsystem_common import ToolSelectPanelHelper + tool = ToolSelectPanelHelper.draw_active_tool_header(context, layout) + 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(_draw_tool_settings_context_mode, tool_mode, None) + if draw_fn is not None: + draw_fn(context, layout, tool) + + # Note: general mode options should be added to 'draw_mode_settings'. + 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="") + + def draw_mode_settings(self, context): + layout = self.layout + + # Active Tool + # ----------- + from .space_toolsystem_common import ToolSelectPanelHelper + tool = ToolSelectPanelHelper.tool_active_from_context(context) + tool_mode = context.mode if tool is None else tool.mode + + 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, + ) + + +class _draw_tool_settings_context_mode: + @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 + # FIXME: tools must use their own UI drawing! + if tool.idname in {"builtin.line", "builtin.box", "builtin.circle", "builtin.arc", "builtin.curve"}: + # is_paint = False + pass + elif tool.idname == "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) + if not gp_settings.use_material_pin: + ma = context.object.active_material + 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 context.object and 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) + + # FIXME: tools must use their own UI drawing! + if tool.idname in {"builtin.arc", "builtin.curve", "builtin.line", "builtin.box", "builtin.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", + ) + + if brush.gpencil_tool == 'FILL': + settings = context.tool_settings.gpencil_sculpt + row = layout.row(align=True) + sub = row.row(align=True) + sub.popover( + panel="TOPBAR_PT_gpencil_fill", + text="Fill Options", + ) + + @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': + 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 VIEW3D_HT_header(Header): + bl_space_type = 'VIEW_3D' + + def draw(self, context): + layout = self.layout + + tool_settings = context.tool_settings + view = context.space_data + shading = view.shading + # mode_string = context.mode + obj = context.active_object + + if not view.show_region_tool_header: + layout.row(align=True).template_header() + + row = layout.row(align=True) + object_mode = 'OBJECT' if obj is None else obj.mode + + # Note: This is actually deadly in case enum_items have to be dynamically generated + # (because internal RNA array iterator will free everything immediately...). + # XXX This is an RNA internal issue, not sure how to fix it. + # Note: Tried to add an accessor to get translated UI strings instead of manual call + # to pgettext_iface below, but this fails because translated enumitems + # are always dynamically allocated. + act_mode_item = bpy.types.Object.bl_rna.properties["mode"].enum_items[object_mode] + act_mode_i18n_context = bpy.types.Object.bl_rna.properties["mode"].translation_context + + sub = row.row(align=True) + sub.ui_units_x = 5.5 + sub.operator_menu_enum( + "object.mode_set", "mode", + text=bpy.app.translations.pgettext_iface(act_mode_item.name, act_mode_i18n_context), + icon=act_mode_item.icon, + ) + del act_mode_item + + layout.template_header_3D_mode() + + # Contains buttons like Mode, Pivot, Layer, Mesh Select Mode... + if obj: + # Particle edit + if object_mode == 'PARTICLE_EDIT': + row = layout.row() + row.prop(tool_settings.particle_edit, "select_mode", text="", expand=True) + + # Grease Pencil + if obj and obj.type == 'GPENCIL' and context.gpencil_data: + gpd = context.gpencil_data + + if gpd.is_stroke_paint_mode: + row = layout.row() + sub = row.row(align=True) + sub.prop(tool_settings, "use_gpencil_draw_onback", text="", icon='MOD_OPACITY') + sub.separator(factor=0.4) + sub.prop(tool_settings, "use_gpencil_weight_data_add", text="", icon='WPAINT_HLT') + sub.separator(factor=0.4) + sub.prop(tool_settings, "use_gpencil_draw_additive", text="", icon='FREEZE') + + if gpd.use_stroke_edit_mode: + row = layout.row(align=True) + row.prop(tool_settings, "gpencil_selectmode", text="", expand=True) + + if gpd.use_stroke_edit_mode or gpd.is_stroke_sculpt_mode or gpd.is_stroke_weight_mode: + row = layout.row(align=True) + + if gpd.is_stroke_sculpt_mode: + row.prop(tool_settings.gpencil_sculpt, "use_select_mask", text="") + row.separator() + + row.prop(gpd, "use_multiedit", text="", icon='GP_MULTIFRAME_EDITING') + + sub = row.row(align=True) + sub.active = gpd.use_multiedit + sub.popover( + panel="VIEW3D_PT_gpencil_multi_frame", + text="Multiframe", + ) + + if gpd.use_stroke_edit_mode: + row = layout.row(align=True) + row.prop(tool_settings.gpencil_sculpt, "use_select_mask", text="") + + row.popover( + panel="VIEW3D_PT_tools_grease_pencil_interpolate", + text="Interpolate", + ) + + overlay = view.overlay + + VIEW3D_MT_editor_menus.draw_collapsible(context, layout) + + layout.separator_spacer() + # Viewport Settings layout.popover( panel="VIEW3D_PT_object_type_visibility", @@ -5910,6 +6263,7 @@ class TOPBAR_PT_gpencil_materials(GreasePencilMaterialsPanel, Panel): classes = ( VIEW3D_HT_header, + VIEW3D_HT_tool_header, VIEW3D_MT_editor_menus, VIEW3D_MT_transform, VIEW3D_MT_transform_base, diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index 9fa70d38574..df018f7cea4 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -868,7 +868,7 @@ void BKE_screen_header_alignment_reset(bScreen *screen) int alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP; for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) { - if (ar->regiontype == RGN_TYPE_HEADER) { + if (ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER)) { if (ELEM(sa->spacetype, SPACE_FILE, SPACE_USERPREF, SPACE_OUTLINER, SPACE_PROPERTIES)) { ar->alignment = RGN_ALIGN_TOP; continue; diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index 523e0b3d340..e43553cd64f 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -591,17 +591,25 @@ static void do_versions_remove_region(ListBase *regionbase, int regiontype) } } -static ARegion *do_versions_find_region(ListBase *regionbase, int regiontype) +static ARegion *do_versions_find_region_or_null(ListBase *regionbase, int regiontype) { for (ARegion *ar = regionbase->first; ar; ar = ar->next) { if (ar->regiontype == regiontype) { return ar; } } - BLI_assert(!"Did not find expected region in versioning"); return NULL; } +static ARegion *do_versions_find_region(ListBase *regionbase, int regiontype) +{ + ARegion *ar = do_versions_find_region_or_null(regionbase, regiontype); + if (ar == NULL) { + BLI_assert(!"Did not find expected region in versioning"); + } + return ar; +} + static ARegion *do_versions_add_region(int regiontype, const char *name) { ARegion *ar = MEM_callocN(sizeof(ARegion), name); @@ -3130,6 +3138,27 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) } } + /* Keep un-versioned until we're finished adding space types. */ + { + for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) { + for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { + for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) { + ListBase *regionbase = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase; + /* All spaces that use tools must be eventually added. */ + if (ELEM(sl->spacetype, SPACE_VIEW3D, SPACE_IMAGE) && + (do_versions_find_region_or_null(regionbase, RGN_TYPE_TOOL_HEADER) == NULL)) { + /* Add tool header. */ + ARegion *ar = do_versions_add_region(RGN_TYPE_TOOL_HEADER, "tool header"); + ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP; + + ARegion *ar_header = do_versions_find_region(regionbase, RGN_TYPE_HEADER); + BLI_insertlinkbefore(regionbase, ar_header, ar); + } + } + } + } + } + { if (!DNA_struct_elem_find(fd->filesdna, "bSplineIKConstraint", "short", "yScaleMode")) { for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) { diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index 04bbbbdf25f..b4349ff6cc7 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -131,10 +131,21 @@ bool ED_region_snap_size_apply(struct ARegion *ar, int snap_flag); void ED_region_do_msg_notify_tag_redraw(struct bContext *C, struct wmMsgSubscribeKey *msg_key, struct wmMsgSubscribeValue *msg_val); +void ED_area_do_msg_notify_tag_redraw(struct bContext *C, + struct wmMsgSubscribeKey *msg_key, + struct wmMsgSubscribeValue *msg_val); void ED_area_do_msg_notify_tag_refresh(struct bContext *C, struct wmMsgSubscribeKey *msg_key, struct wmMsgSubscribeValue *msg_val); +void ED_area_do_mgs_subscribe_for_tool_header(const struct bContext *C, + struct WorkSpace *workspace, + struct Scene *scene, + struct bScreen *screen, + struct ScrArea *sa, + struct ARegion *ar, + struct wmMsgBus *mbus); + /* message bus */ void ED_region_message_subscribe(struct bContext *C, struct WorkSpace *workspace, diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c index c8800f495ce..b6d9863f9b5 100644 --- a/source/blender/editors/interface/interface_context_menu.c +++ b/source/blender/editors/interface/interface_context_menu.c @@ -1064,7 +1064,7 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but) if (!ar) { /* skip */ } - else if (ar->regiontype == RGN_TYPE_HEADER) { + else if (ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER)) { uiItemMenuF(layout, IFACE_("Header"), ICON_NONE, ED_screens_header_tools_menu_create, NULL); } else if (ar->regiontype == RGN_TYPE_NAV_BAR) { diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index e9914ce6f24..72aa9920248 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -1778,7 +1778,11 @@ static bool ui_but_drag_init(bContext *C, /* Initialize alignment for single row/column regions, * otherwise we use the relative position of the first other button dragged over. */ - if (ELEM(data->region->regiontype, RGN_TYPE_NAV_BAR, RGN_TYPE_HEADER, RGN_TYPE_FOOTER)) { + if (ELEM(data->region->regiontype, + RGN_TYPE_NAV_BAR, + RGN_TYPE_HEADER, + RGN_TYPE_TOOL_HEADER, + RGN_TYPE_FOOTER)) { int lock_axis = -1; if (ELEM(data->region->alignment, RGN_ALIGN_LEFT, RGN_ALIGN_RIGHT)) { lock_axis = 0; diff --git a/source/blender/editors/interface/interface_region_menu_popup.c b/source/blender/editors/interface/interface_region_menu_popup.c index d364bf7e102..b97cbcdfef5 100644 --- a/source/blender/editors/interface/interface_region_menu_popup.c +++ b/source/blender/editors/interface/interface_region_menu_popup.c @@ -279,7 +279,7 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); if (sa && ar) { - if (ar->regiontype == RGN_TYPE_HEADER) { + if (ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER)) { if (ED_area_header_alignment(sa) == RGN_ALIGN_BOTTOM) { UI_block_direction_set(block, UI_DIR_UP); UI_block_order_flip(block); diff --git a/source/blender/editors/interface/interface_region_popover.c b/source/blender/editors/interface/interface_region_popover.c index bbf3df6a264..110c8827849 100644 --- a/source/blender/editors/interface/interface_region_popover.c +++ b/source/blender/editors/interface/interface_region_popover.c @@ -187,7 +187,7 @@ static uiBlock *ui_block_func_POPOVER(bContext *C, uiPopupBlockHandle *handle, v } /* Prefer popover from header to be positioned into the editor. */ else if (sa && ar) { - if (ar->regiontype == RGN_TYPE_HEADER) { + if (ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER)) { if (ED_area_header_alignment(sa) == RGN_ALIGN_BOTTOM) { UI_block_direction_set(block, UI_DIR_UP | UI_DIR_CENTER_X); } diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 76d82b93ad1..bbff2c16636 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -127,11 +127,8 @@ static void template_add_button_search_menu(const bContext *C, if (use_previews) { ARegion *region = CTX_wm_region(C); - ScrArea *area = CTX_wm_area(C); - /* XXX ugly top-bar exception */ - const bool use_big_size = ( - /* silly check, could be more generic */ - (region->regiontype != RGN_TYPE_HEADER) && (area->spacetype != SPACE_TOPBAR)); + /* Ugly tool header exception. */ + const bool use_big_size = (region->regiontype != RGN_TYPE_TOOL_HEADER); /* Ugly exception for screens here, * drawing their preview in icon size looks ugly/useless */ const bool use_preview_icon = use_big_size || (id && (GS(id->name) != ID_SCR)); diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 1aa54bcd8b5..250a4171e8a 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -421,17 +421,18 @@ static void region_draw_status_text(ScrArea *sa, ARegion *ar) BLF_draw(fontid, ar->headerstr, BLF_DRAW_STR_DUMMY_MAX); } -/* Follow wmMsgNotifyFn spec */ -void ED_region_do_msg_notify_tag_redraw(bContext *UNUSED(C), - wmMsgSubscribeKey *UNUSED(msg_key), - wmMsgSubscribeValue *msg_val) +void ED_region_do_msg_notify_tag_redraw( + /* Follow wmMsgNotifyFn spec */ + bContext *UNUSED(C), + wmMsgSubscribeKey *UNUSED(msg_key), + wmMsgSubscribeValue *msg_val) { ARegion *ar = msg_val->owner; ED_region_tag_redraw(ar); /* This avoids _many_ situations where header/properties control display settings. * the common case is space properties in the header */ - if (ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_UI)) { + if (ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER, RGN_TYPE_UI)) { while (ar && ar->prev) { ar = ar->prev; } @@ -442,15 +443,48 @@ void ED_region_do_msg_notify_tag_redraw(bContext *UNUSED(C), } } } -/* Follow wmMsgNotifyFn spec */ -void ED_area_do_msg_notify_tag_refresh(bContext *UNUSED(C), - wmMsgSubscribeKey *UNUSED(msg_key), - wmMsgSubscribeValue *msg_val) +/** + * Use #ED_region_do_msg_notify_tag_redraw where possible, this draws too much typically. + */ +void ED_area_do_msg_notify_tag_redraw( + /* Follow wmMsgNotifyFn spec */ + bContext *UNUSED(C), + wmMsgSubscribeKey *UNUSED(msg_key), + wmMsgSubscribeValue *msg_val) +{ + ScrArea *sa = msg_val->owner; + ED_area_tag_redraw(sa); +} +void ED_area_do_msg_notify_tag_refresh( + /* Follow wmMsgNotifyFn spec */ + bContext *UNUSED(C), + wmMsgSubscribeKey *UNUSED(msg_key), + wmMsgSubscribeValue *msg_val) { ScrArea *sa = msg_val->user_data; ED_area_tag_refresh(sa); } +void ED_area_do_mgs_subscribe_for_tool_header( + /* Follow ARegionType.message_subscribe */ + const struct bContext *UNUSED(C), + struct WorkSpace *workspace, + struct Scene *UNUSED(scene), + struct bScreen *UNUSED(screen), + struct ScrArea *sa, + struct ARegion *UNUSED(ar), + struct wmMsgBus *mbus) +{ + /* TODO(campbell): investigate why ED_region_do_msg_notify_tag_redraw doesn't work here. */ + wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { + .owner = sa, + .user_data = sa, + .notify = ED_area_do_msg_notify_tag_redraw, + }; + WM_msg_subscribe_rna_prop( + mbus, &workspace->id, workspace, WorkSpace, tools, &msg_sub_value_region_tag_redraw); +} + /** * Although there's no general support for minimizing areas, the status-bar can * be snapped to be only a few pixels high. A few pixels rather than 0 so it @@ -931,7 +965,7 @@ static bool region_azone_edge_poll(const ARegion *ar, const bool is_fullscreen) if (is_hidden && is_fullscreen) { return false; } - if (!is_hidden && ar->regiontype == RGN_TYPE_HEADER) { + if (!is_hidden && ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER)) { return false; } @@ -1011,6 +1045,12 @@ static void region_azones_add(const bScreen *screen, ScrArea *sa, ARegion *ar, c { const bool is_fullscreen = screen->state == SCREENFULL; + /* Only display tab or icons when the header region is hidden + * (not the tool header - they overlap). */ + if (ar->regiontype == RGN_TYPE_TOOL_HEADER) { + return; + } + /* edge code (t b l r) is along which area edge azone will be drawn */ if (alignment == RGN_ALIGN_TOP) region_azone_edge_initialize(sa, ar, AE_BOTTOM_TO_TOPLEFT, is_fullscreen); @@ -1183,6 +1223,9 @@ static void region_rect_recursive( else if (ar->regiontype == RGN_TYPE_HEADER) { prefsizey = ED_area_headersize(); } + else if (ar->regiontype == RGN_TYPE_TOOL_HEADER) { + prefsizey = ED_area_headersize(); + } else if (ar->regiontype == RGN_TYPE_FOOTER) { prefsizey = ED_area_footersize(); } @@ -1937,7 +1980,7 @@ void ED_area_newspace(bContext *C, ScrArea *sa, int type, const bool skip_ar_exi /* Spaces with footer. */ if (st->spaceid == SPACE_TEXT) { for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) { - if (ar->regiontype == RGN_TYPE_HEADER) { + if (ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER)) { ar->alignment = header_alignment; } if (ar->regiontype == RGN_TYPE_FOOTER) { @@ -1950,7 +1993,7 @@ void ED_area_newspace(bContext *C, ScrArea *sa, int type, const bool skip_ar_exi } else { for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) { - if (ar->regiontype == RGN_TYPE_HEADER) { + if (ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER)) { ar->alignment = header_alignment; break; } @@ -2035,6 +2078,7 @@ static ThemeColorID region_background_color_id(const bContext *C, const ARegion switch (region->regiontype) { case RGN_TYPE_HEADER: + case RGN_TYPE_TOOL_HEADER: if (ED_screen_area_active(C) || ED_area_is_global(area)) { return TH_HEADER; } diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index 8caa960bb9a..259076f194f 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -428,6 +428,10 @@ static void screen_refresh_headersizes(void) if (art) art->prefsizey = ED_area_headersize(); + art = BKE_regiontype_from_id(st, RGN_TYPE_TOOL_HEADER); + if (art) + art->prefsizey = ED_area_headersize(); + art = BKE_regiontype_from_id(st, RGN_TYPE_FOOTER); if (art) art->prefsizey = ED_area_headersize(); @@ -679,7 +683,7 @@ void ED_screen_set_active_region(bContext *C, wmWindow *win, const int xy[2]) if (do_draw) { for (ar = area_iter->regionbase.first; ar; ar = ar->next) { - if (ar->regiontype == RGN_TYPE_HEADER) { + if (ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER)) { ED_region_tag_redraw_no_rebuild(ar); } } @@ -813,16 +817,14 @@ static int screen_global_header_size(void) static void screen_global_topbar_area_refresh(wmWindow *win, bScreen *screen) { - const short size_min = screen_global_header_size(); - const short size_max = 2.25 * screen_global_header_size(); - const short size = (screen->flag & SCREEN_COLLAPSE_TOPBAR) ? size_min : size_max; + const short size = screen_global_header_size(); rcti rect; BLI_rcti_init(&rect, 0, WM_window_pixels_x(win) - 1, 0, WM_window_pixels_y(win) - 1); - rect.ymin = rect.ymax - size_max; + rect.ymin = rect.ymax - size; screen_global_area_refresh( - win, screen, SPACE_TOPBAR, GLOBAL_AREA_ALIGN_TOP, &rect, size, size_min, size_max); + win, screen, SPACE_TOPBAR, GLOBAL_AREA_ALIGN_TOP, &rect, size, size, size); } static void screen_global_statusbar_area_refresh(wmWindow *win, bScreen *screen) @@ -845,14 +847,11 @@ void ED_screen_global_areas_sync(wmWindow *win) * global areas should just become part of the screen instead. */ bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook); - screen->flag &= ~(SCREEN_COLLAPSE_STATUSBAR | SCREEN_COLLAPSE_TOPBAR); + screen->flag &= ~SCREEN_COLLAPSE_STATUSBAR; for (ScrArea *area = win->global_areas.areabase.first; area; area = area->next) { if (area->global->cur_fixed_height == area->global->size_min) { - if (area->spacetype == SPACE_TOPBAR) { - screen->flag |= SCREEN_COLLAPSE_TOPBAR; - } - else if (area->spacetype == SPACE_STATUSBAR) { + if (area->spacetype == SPACE_STATUSBAR) { screen->flag |= SCREEN_COLLAPSE_STATUSBAR; } } @@ -1278,6 +1277,7 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *sa, const s if (ELEM(ar->regiontype, RGN_TYPE_UI, RGN_TYPE_HEADER, + RGN_TYPE_TOOL_HEADER, RGN_TYPE_FOOTER, RGN_TYPE_TOOLS, RGN_TYPE_NAV_BAR, diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 07f60552ce4..4e39f56ddee 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -1324,7 +1324,7 @@ static void area_move_set_limits( int size_max = ED_area_global_max_size_y(area) - 1; size_min = max_ii(size_min, 0); - BLI_assert(size_min < size_max); + BLI_assert(size_min <= size_max); /* logic here is only tested for lower edge :) */ /* left edge */ @@ -2338,12 +2338,12 @@ static int area_max_regionsize(ScrArea *sa, ARegion *scalear, AZEdge edge) } else if (scalear->alignment == RGN_ALIGN_TOP && (ar->alignment == RGN_ALIGN_BOTTOM || - ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_FOOTER))) { + ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER, RGN_TYPE_FOOTER))) { dist -= ar->winy; } else if (scalear->alignment == RGN_ALIGN_BOTTOM && (ar->alignment == RGN_ALIGN_TOP || - ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_FOOTER))) { + ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER, RGN_TYPE_FOOTER))) { dist -= ar->winy; } } @@ -2430,6 +2430,18 @@ static void region_scale_toggle_hidden(bContext *C, RegionMoveData *rmd) region_toggle_hidden(C, rmd->ar, 0); region_scale_validate_size(rmd); + + if ((rmd->ar->flag & RGN_FLAG_HIDDEN) == 0) { + if (rmd->ar->regiontype == RGN_TYPE_HEADER) { + ARegion *ar_tool_header = BKE_area_find_region_type(rmd->sa, RGN_TYPE_TOOL_HEADER); + if (ar_tool_header != NULL) { + if ((ar_tool_header->flag & RGN_FLAG_HIDDEN_BY_USER) == 0 && + (ar_tool_header->flag & RGN_FLAG_HIDDEN) != 0) { + region_toggle_hidden(C, ar_tool_header, 0); + } + } + } + } } static int region_scale_modal(bContext *C, wmOperator *op, const wmEvent *event) @@ -3794,11 +3806,16 @@ void ED_screens_header_tools_menu_create(bContext *C, uiLayout *layout, void *UN ARegion *ar = CTX_wm_region(C); const char *but_flip_str = (ar->alignment == RGN_ALIGN_TOP) ? IFACE_("Flip to Bottom") : IFACE_("Flip to Top"); - - if (!ELEM(sa->spacetype, SPACE_TOPBAR)) { + { PointerRNA ptr; RNA_pointer_create((ID *)CTX_wm_screen(C), &RNA_Space, sa->spacedata.first, &ptr); uiItemR(layout, &ptr, "show_region_header", 0, IFACE_("Show Header"), ICON_NONE); + if (BKE_area_find_region_type(sa, RGN_TYPE_TOOL_HEADER)) { + ARegion *ar_header = BKE_area_find_region_type(sa, RGN_TYPE_HEADER); + uiLayoutSetActive(layout, (ar_header->flag & RGN_FLAG_HIDDEN) == 0); + uiItemR(layout, &ptr, "show_region_tool_header", 0, IFACE_("Show Tool Settings"), ICON_NONE); + uiLayoutSetActive(layout, true); + } } /* default is WM_OP_INVOKE_REGION_WIN, which we don't want here. */ @@ -4058,7 +4075,7 @@ static int match_region_with_redraws(int spacetype, if (redraws & TIME_ALL_BUTS_WIN) return 1; } - else if (regiontype == RGN_TYPE_HEADER) { + else if (ELEM(regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER)) { if (spacetype == SPACE_ACTION) return 1; } diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index ded19b10300..1e1d1e570b3 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -134,6 +134,13 @@ static SpaceLink *image_new(const ScrArea *UNUSED(area), const Scene *UNUSED(sce scopes_new(&simage->scopes); simage->sample_line_hist.height = 100; + /* tool header */ + ar = MEM_callocN(sizeof(ARegion), "tool header for image"); + + BLI_addtail(&simage->regionbase, ar); + ar->regiontype = RGN_TYPE_TOOL_HEADER; + ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP; + /* header */ ar = MEM_callocN(sizeof(ARegion), "header for image"); @@ -1033,6 +1040,17 @@ void ED_spacetype_image(void) art->draw = image_tools_region_draw; BLI_addhead(&st->regiontypes, art); + /* regions: tool header */ + art = MEM_callocN(sizeof(ARegionType), "spacetype image tool header region"); + art->regionid = RGN_TYPE_TOOL_HEADER; + art->prefsizey = HEADERY; + art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER; + art->listener = image_header_region_listener; + art->init = image_header_region_init; + art->draw = image_header_region_draw; + art->message_subscribe = ED_area_do_mgs_subscribe_for_tool_header; + BLI_addhead(&st->regiontypes, art); + /* regions: header */ art = MEM_callocN(sizeof(ARegionType), "spacetype image region"); art->regionid = RGN_TYPE_HEADER; diff --git a/source/blender/editors/space_topbar/space_topbar.c b/source/blender/editors/space_topbar/space_topbar.c index 46a86bcbc86..8b290009a97 100644 --- a/source/blender/editors/space_topbar/space_topbar.c +++ b/source/blender/editors/space_topbar/space_topbar.c @@ -71,10 +71,6 @@ static SpaceLink *topbar_new(const ScrArea *UNUSED(area), const Scene *UNUSED(sc ar->alignment = RGN_ALIGN_RIGHT | RGN_SPLIT_PREV; /* main regions */ - ar = MEM_callocN(sizeof(ARegion), "right aligned main region for topbar"); - BLI_addtail(&stopbar->regionbase, ar); - ar->regiontype = RGN_TYPE_WINDOW; - ar->alignment = RGN_ALIGN_RIGHT; ar = MEM_callocN(sizeof(ARegion), "main region of topbar"); BLI_addtail(&stopbar->regionbase, ar); ar->regiontype = RGN_TYPE_WINDOW; diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index a829584b580..8a0d1b5b322 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -293,6 +293,13 @@ static SpaceLink *view3d_new(const ScrArea *UNUSED(sa), const Scene *scene) v3d->vertex_opacity = 1.0f; v3d->gp_flag |= V3D_GP_SHOW_EDIT_LINES; + /* tool header */ + ar = MEM_callocN(sizeof(ARegion), "tool header for view3d"); + + BLI_addtail(&v3d->regionbase, ar); + ar->regiontype = RGN_TYPE_TOOL_HEADER; + ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP; + /* header */ ar = MEM_callocN(sizeof(ARegion), "header for view3d"); @@ -1120,6 +1127,34 @@ static void view3d_header_region_listener(wmWindow *UNUSED(win), } break; } + + /* From topbar, which ones are needed? split per header? */ + /* Disable for now, re-enable if neede, or remove - campbell. */ +#if 0 + /* context changes */ + switch (wmn->category) { + case NC_WM: + if (wmn->data == ND_HISTORY) { + ED_region_tag_redraw(ar); + } + break; + case NC_SCENE: + if (wmn->data == ND_MODE) { + ED_region_tag_redraw(ar); + } + break; + case NC_SPACE: + if (wmn->data == ND_SPACE_VIEW3D) { + ED_region_tag_redraw(ar); + } + break; + case NC_GPENCIL: + if (wmn->data == ND_DATA) { + ED_region_tag_redraw(ar); + } + break; + } +#endif } static void view3d_header_region_message_subscribe(const struct bContext *UNUSED(C), @@ -1489,6 +1524,17 @@ void ED_spacetype_view3d(void) art->draw = view3d_tools_region_draw; BLI_addhead(&st->regiontypes, art); + /* regions: tool header */ + art = MEM_callocN(sizeof(ARegionType), "spacetype view3d tool header region"); + art->regionid = RGN_TYPE_TOOL_HEADER; + art->prefsizey = HEADERY; + art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER; + art->listener = view3d_header_region_listener; + art->init = view3d_header_region_init; + art->draw = view3d_header_region_draw; + art->message_subscribe = view3d_header_region_message_subscribe; + BLI_addhead(&st->regiontypes, art); + /* regions: header */ art = MEM_callocN(sizeof(ARegionType), "spacetype view3d header region"); art->regionid = RGN_TYPE_HEADER; @@ -1497,7 +1543,7 @@ void ED_spacetype_view3d(void) art->listener = view3d_header_region_listener; art->init = view3d_header_region_init; art->draw = view3d_header_region_draw; - art->message_subscribe = view3d_header_region_message_subscribe; + art->message_subscribe = ED_area_do_mgs_subscribe_for_tool_header; BLI_addhead(&st->regiontypes, art); /* regions: hud */ diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h index 747c8d4152d..59d307645ac 100644 --- a/source/blender/makesdna/DNA_screen_types.h +++ b/source/blender/makesdna/DNA_screen_types.h @@ -471,7 +471,7 @@ enum { /** #bScreen.flag */ enum { - SCREEN_COLLAPSE_TOPBAR = 1, + SCREEN_DEPRECATED = 1, SCREEN_COLLAPSE_STATUSBAR = 2, }; @@ -589,6 +589,7 @@ enum { /* A place for buttons to trigger execution of something that was set up in other regions. */ RGN_TYPE_EXECUTE = 10, RGN_TYPE_FOOTER = 11, + RGN_TYPE_TOOL_HEADER = 12, }; /* use for function args */ #define RGN_TYPE_ANY -1 diff --git a/source/blender/makesrna/intern/rna_screen.c b/source/blender/makesrna/intern/rna_screen.c index 5913376606b..89996cf3241 100644 --- a/source/blender/makesrna/intern/rna_screen.c +++ b/source/blender/makesrna/intern/rna_screen.c @@ -43,6 +43,7 @@ const EnumPropertyItem rna_enum_region_type_items[] = { {RGN_TYPE_NAV_BAR, "NAVIGATION_BAR", 0, "Navigation Bar", ""}, {RGN_TYPE_EXECUTE, "EXECUTE", 0, "Execute Buttons", ""}, {RGN_TYPE_FOOTER, "FOOTER", 0, "Footer", ""}, + {RGN_TYPE_TOOL_HEADER, "TOOL_HEADER", 0, "Tool Header", ""}, {0, NULL, 0, NULL, NULL}, }; @@ -550,11 +551,6 @@ static void rna_def_screen(BlenderRNA *brna) RNA_def_property_boolean_funcs(prop, "rna_Screen_fullscreen_get", NULL); RNA_def_property_ui_text(prop, "Maximize", "An area is maximized, filling this screen"); - prop = RNA_def_property(srna, "show_topbar", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SCREEN_COLLAPSE_TOPBAR); - RNA_def_property_ui_text(prop, "Show Top Bar", "Show top bar with tool settings"); - RNA_def_property_update(prop, 0, "rna_Screen_bar_update"); - prop = RNA_def_property(srna, "show_statusbar", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SCREEN_COLLAPSE_STATUSBAR); RNA_def_property_ui_text(prop, "Show Status Bar", "Show status bar"); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 04032d0863a..984536b6907 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -622,12 +622,44 @@ static bool rna_Space_show_region_header_get(PointerRNA *ptr) static void rna_Space_show_region_header_set(PointerRNA *ptr, bool value) { rna_Space_bool_from_region_flag_set_by_type(ptr, RGN_TYPE_HEADER, RGN_FLAG_HIDDEN, !value); + + /* Special case, never show the tool properties when the header is invisible. */ + bool value_for_tool_header = value; + if (value == true) { + ScrArea *sa = rna_area_from_space(ptr); + ARegion *ar_tool_header = BKE_area_find_region_type(sa, RGN_TYPE_TOOL_HEADER); + if (ar_tool_header != NULL) { + value = !(ar_tool_header->flag & RGN_FLAG_HIDDEN_BY_USER); + } + } + rna_Space_bool_from_region_flag_set_by_type( + ptr, RGN_TYPE_TOOL_HEADER, RGN_FLAG_HIDDEN, !value_for_tool_header); } static void rna_Space_show_region_header_update(bContext *C, PointerRNA *ptr) { rna_Space_bool_from_region_flag_update_by_type(C, ptr, RGN_TYPE_HEADER, RGN_FLAG_HIDDEN); } +/* Tool Header Region. + * + * This depends on the 'RGN_TYPE_TOOL_HEADER' + */ +static bool rna_Space_show_region_tool_header_get(PointerRNA *ptr) +{ + return !rna_Space_bool_from_region_flag_get_by_type( + ptr, RGN_TYPE_TOOL_HEADER, RGN_FLAG_HIDDEN_BY_USER); +} +static void rna_Space_show_region_tool_header_set(PointerRNA *ptr, bool value) +{ + rna_Space_bool_from_region_flag_set_by_type( + ptr, RGN_TYPE_TOOL_HEADER, RGN_FLAG_HIDDEN_BY_USER, !value); + rna_Space_bool_from_region_flag_set_by_type(ptr, RGN_TYPE_TOOL_HEADER, RGN_FLAG_HIDDEN, !value); +} +static void rna_Space_show_region_tool_header_update(bContext *C, PointerRNA *ptr) +{ + rna_Space_bool_from_region_flag_update_by_type(C, ptr, RGN_TYPE_TOOL_HEADER, RGN_FLAG_HIDDEN); +} + /* Tools Region. */ static bool rna_Space_show_region_toolbar_get(PointerRNA *ptr) { @@ -2422,6 +2454,10 @@ static void rna_def_space_generic_show_region_toggles(StructRNA *srna, int regio } \ ((void)0) + if (region_type_mask & (1 << RGN_TYPE_TOOL_HEADER)) { + region_type_mask &= ~(1 << RGN_TYPE_TOOL_HEADER); + DEF_SHOW_REGION_PROPERTY(show_region_tool_header, "Tool Header", ""); + } if (region_type_mask & (1 << RGN_TYPE_HEADER)) { region_type_mask &= ~(1 << RGN_TYPE_HEADER); DEF_SHOW_REGION_PROPERTY(show_region_header, "Header", ""); @@ -3546,8 +3582,9 @@ static void rna_def_space_view3d(BlenderRNA *brna) RNA_def_struct_sdna(srna, "View3D"); RNA_def_struct_ui_text(srna, "3D View Space", "3D View space data"); - rna_def_space_generic_show_region_toggles( - srna, (1 << RGN_TYPE_TOOLS) | (1 << RGN_TYPE_UI) | (1 << RGN_TYPE_HUD)); + rna_def_space_generic_show_region_toggles(srna, + ((1 << RGN_TYPE_TOOL_HEADER) | (1 << RGN_TYPE_TOOLS) | + (1 << RGN_TYPE_UI) | (1 << RGN_TYPE_HUD))); prop = RNA_def_property(srna, "camera", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_EDITABLE); @@ -4054,7 +4091,7 @@ static void rna_def_space_image(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "Space Image Editor", "Image and UV editor space data"); rna_def_space_generic_show_region_toggles( - srna, (1 << RGN_TYPE_TOOLS) | (1 << RGN_TYPE_UI) | (1 << RGN_TYPE_HUD)); + srna, (1 << RGN_TYPE_TOOL_HEADER) | (1 << RGN_TYPE_TOOLS) | (1 << RGN_TYPE_UI) | (1 << RGN_TYPE_HUD)); /* image */ prop = RNA_def_property(srna, "image", PROP_POINTER, PROP_NONE); diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 1cc45653087..d61f9be170d 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -1463,7 +1463,7 @@ static int wm_operator_invoke(bContext *C, /* exception, cont. grab in header is annoying */ if (wrap) { ARegion *ar = CTX_wm_region(C); - if (ar && ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_FOOTER)) { + if (ar && ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER, RGN_TYPE_FOOTER)) { wrap = false; } } @@ -4926,7 +4926,12 @@ void WM_window_cursor_keymap_status_refresh(bContext *C, wmWindow *win) if (ELEM(sa->spacetype, SPACE_STATUSBAR, SPACE_TOPBAR)) { return; } - if (ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_FOOTER, RGN_TYPE_TEMPORARY, RGN_TYPE_HUD)) { + if (ELEM(ar->regiontype, + RGN_TYPE_HEADER, + RGN_TYPE_TOOL_HEADER, + RGN_TYPE_FOOTER, + RGN_TYPE_TEMPORARY, + RGN_TYPE_HUD)) { return; } /* Fallback to window. */ |