diff --git a/scripts/startup/bl_ui/space_properties.py b/scripts/startup/bl_ui/space_properties.py index a672daacba9..280b970f657 100644 --- a/scripts/startup/bl_ui/space_properties.py +++ b/scripts/startup/bl_ui/space_properties.py @@ -10,32 +10,36 @@ from bpy.app.translations import ( ) +tab_list = [ + ("show_properties_tool", "Tool", 'TOOL_SETTINGS'), + ("show_properties_render", "Render", 'SCENE'), + ("show_properties_output", "Output", 'OUTPUT'), + ("show_properties_view_layer", "View Layer", 'RENDERLAYERS'), + ("show_properties_scene", "Scene", 'SCENE_DATA'), + ("show_properties_world", "World", 'WORLD'), + ("show_properties_collection", "Collection", 'OUTLINER_COLLECTION'), + ("show_properties_object", "Object", 'OBJECT_DATA'), + ("show_properties_modifiers", "Modifiers", 'MODIFIER'), + ("show_properties_effects", "Effects", 'SHADERFX'), + ("show_properties_particles", "Particles", 'PARTICLES'), + ("show_properties_physics", "Physics", 'PHYSICS'), + ("show_properties_constraints", "Constraints", 'CONSTRAINT'), + ("show_properties_data", "Data", 'MESH_DATA'), + ("show_properties_bone", "Bone", 'BONE_DATA'), + ("show_properties_bone_constraints", "Bone Constraints", 'CONSTRAINT_BONE'), + ("show_properties_material", "Material", 'MATERIAL'), + ("show_properties_texture", "Texture", 'TEXTURE'), + ("show_properties_strip", "Strip", 'SEQ_SEQUENCER'), + ("show_properties_strip_modifier", "Strip Modifiers", 'SEQ_STRIP_MODIFIER'), +] + + class PROPERTIES_HT_header(Header): bl_space_type = 'PROPERTIES' @staticmethod def _search_poll(space): - return (space.show_properties_tool or - space.show_properties_render or - space.show_properties_output or - space.show_properties_view_layer or - space.show_properties_scene or - space.show_properties_world or - space.show_properties_collection or - space.show_properties_object or - space.show_properties_modifiers or - space.show_properties_effects or - space.show_properties_particles or - space.show_properties_physics or - space.show_properties_constraints or - space.show_properties_data or - space.show_properties_bone or - space.show_properties_bone_constraints or - space.show_properties_material or - space.show_properties_texture or - space.show_properties_strip or - space.show_properties_strip_modifier - ) + return any(getattr(space, tab_info[0]) for tab_info in tab_list) def draw(self, context): layout = self.layout @@ -64,6 +68,10 @@ class PROPERTIES_HT_header(Header): layout.popover(panel="PROPERTIES_PT_options", text="") +def has_hidden_tabs(space): + return not all(getattr(space, tab_info[0]) for tab_info in tab_list) + + class PROPERTIES_PT_navigation_bar(Panel): bl_space_type = 'PROPERTIES' bl_region_type = 'NAVIGATION_BAR' @@ -85,6 +93,17 @@ class PROPERTIES_PT_navigation_bar(Panel): else: layout.prop_tabs_enum(view, "context", icon_only=True) + # Scale sub layout to make the popover button smaller and use separator to + # offset it, such that it is centered. + sub = layout.row(align=True) + sub.alignment = 'CENTER' + sub.emboss = 'NONE' + sub.scale_x = 0.8 + sub.scale_y = 0.8 + sub.separator(factor=0.7) + sub.popover(panel="PROPERTIES_PT_visibility", text="") + sub.active = has_hidden_tabs(view) + class PROPERTIES_PT_options(Panel): """Show options for the properties editor""" @@ -101,40 +120,6 @@ class PROPERTIES_PT_options(Panel): col.label(text="Sync with Outliner") col.row().prop(space, "outliner_sync", expand=True) - layout.separator() - - layout.use_property_decorate = False - - visible_tabs = [ - ("show_properties_tool", "Tool", 'TOOL_SETTINGS'), - ("show_properties_render", "Render", 'SCENE'), - ("show_properties_output", "Output", 'OUTPUT'), - ("show_properties_view_layer", "View Layer", 'RENDERLAYERS'), - ("show_properties_scene", "Scene", 'SCENE_DATA'), - ("show_properties_world", "World", 'WORLD'), - ("show_properties_collection", "Collection", 'GROUP'), - ("show_properties_object", "Object", 'OBJECT_DATA'), - ("show_properties_modifiers", "Modifiers", 'MODIFIER'), - ("show_properties_effects", "Effects", 'SHADERFX'), - ("show_properties_particles", "Particles", 'PARTICLES'), - ("show_properties_physics", "Physics", 'PHYSICS'), - ("show_properties_constraints", "Constraints", 'CONSTRAINT'), - ("show_properties_data", "Data", 'MESH_DATA'), - ("show_properties_bone", "Bone", 'BONE_DATA'), - ("show_properties_bone_constraints", "Bone Constraints", 'CONSTRAINT_BONE'), - ("show_properties_material", "Material", 'MATERIAL'), - ("show_properties_texture", "Texture", 'TEXTURE'), - ("show_properties_strip", "Strip", 'SEQ_SEQUENCER'), - ("show_properties_strip_modifier", "Strip Modifiers", 'SEQ_STRIP_MODIFIER') - ] - - col = layout.column(align=True) - col.label(text="Visible Tabs") - for prop, name, icon in visible_tabs: - row = col.row(align=True) - row.label(text=iface_(name), icon=icon) - row.prop(space, prop, text="") - class PropertiesAnimationMixin: """Mix-in class for Animation panels. @@ -188,10 +173,30 @@ class PropertiesAnimationMixin: anim.draw_action_and_slot_selector_for_id(layout, animated_id) +class PROPERTIES_PT_visibility(Panel): + """Choose visibility of tabs in the properties editor""" + bl_space_type = 'PROPERTIES' + bl_region_type = 'HEADER' + bl_label = "Visibility" + + def draw(self, context): + space = context.space_data + layout = self.layout + layout.use_property_decorate = False + + col = layout.column(align=True) + col.label(text="Visible Tabs") + for prop, name, icon in tab_list: + row = col.row(align=True) + row.label(text=iface_(name), icon=icon) + row.prop(space, prop, text="") + + classes = ( PROPERTIES_HT_header, PROPERTIES_PT_navigation_bar, PROPERTIES_PT_options, + PROPERTIES_PT_visibility, ) if __name__ == "__main__": # only for live edit. diff --git a/source/blender/editors/interface/interface_layout.cc b/source/blender/editors/interface/interface_layout.cc index 1d1a8aad281..2bd489bc99e 100644 --- a/source/blender/editors/interface/interface_layout.cc +++ b/source/blender/editors/interface/interface_layout.cc @@ -3049,6 +3049,12 @@ void uiLayout::popover(const bContext *C, uiBut *but = ui_item_menu( layout, name, icon, ui_item_paneltype_func, pt, nullptr, TIP_(pt->description), true); but->type = ButType::Popover; + + /* Override button size when there is no icon or label. */ + if (layout->root()->type == blender::ui::LayoutType::VerticalBar && !icon && name.is_empty()) { + but->rect.xmax = but->rect.xmin + UI_UNIT_X; + } + if (!ok) { but->flag |= UI_BUT_DISABLED; } diff --git a/source/blender/editors/interface/interface_widgets.cc b/source/blender/editors/interface/interface_widgets.cc index 5ffd245fae6..2282ab9bc4b 100644 --- a/source/blender/editors/interface/interface_widgets.cc +++ b/source/blender/editors/interface/interface_widgets.cc @@ -124,6 +124,8 @@ struct uiWidgetStateInfo { int but_flag; /** Copy of #uiBut.drawflag (possibly with overrides for drawing). */ int but_drawflag; + /** Copy of #uiBut.emboss. */ + blender::ui::EmbossType emboss; /** Show that holding the button opens a menu. */ bool has_hold_action : 1; @@ -3709,7 +3711,7 @@ static void widget_numbut(uiBut *but, static void widget_menubut(uiWidgetColors *wcol, rcti *rect, - const uiWidgetStateInfo * /*state*/, + const uiWidgetStateInfo *state, int roundboxalign, const float zoom) { @@ -3724,6 +3726,12 @@ static void widget_menubut(uiWidgetColors *wcol, /* copy size and center to 2nd tria */ wtb.tria2 = wtb.tria1; + if (ELEM(state->emboss, blender::ui::EmbossType::NoneOrStatus, blender::ui::EmbossType::None)) { + wtb.draw_inner = false; + wtb.draw_outline = false; + wtb.draw_emboss = false; + } + widgetbase_draw(&wtb, wcol); /* text space, arrows are about 0.6 height of button */ @@ -5019,6 +5027,22 @@ static int widget_roundbox_set(uiBut *but, rcti *rect) return roundbox; } +static uiWidgetType *popover_widget_type(uiBut *but, rcti *rect) +{ + /* We could use a flag for this, but for now just check size, + * add up/down arrows if there is room. */ + if ((but->str.empty() && but->icon && (BLI_rcti_size_x(rect) < BLI_rcti_size_y(rect) + 2)) || + /* disable for brushes also */ + (but->flag & UI_BUT_ICON_PREVIEW)) + { + /* No arrows. */ + return widget_type(UI_WTYPE_MENU_ICON_RADIO); + } + + /* With menu arrows. */ + return widget_type(UI_WTYPE_MENU_RADIO); +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -5068,6 +5092,9 @@ void ui_draw_but(const bContext *C, ARegion *region, uiStyle *style, uiBut *but, case ButType::PreviewTile: wt = widget_type(UI_WTYPE_PREVIEW_TILE); break; + case ButType::Popover: + wt = popover_widget_type(but, rect); + break; case ButType::NodeSocket: wt = widget_type(UI_WTYPE_NODESOCKET); break; @@ -5184,21 +5211,8 @@ void ui_draw_but(const bContext *C, ARegion *region, uiStyle *style, uiBut *but, wt = widget_type(UI_WTYPE_MENU_NODE_LINK); } else { - /* with menu arrows */ - - /* We could use a flag for this, but for now just check size, - * add up/down arrows if there is room. */ - if ((but->str.empty() && but->icon && - (BLI_rcti_size_x(rect) < BLI_rcti_size_y(rect) + 2)) || - /* disable for brushes also */ - (but->flag & UI_BUT_ICON_PREVIEW)) - { - /* no arrows */ - wt = widget_type(UI_WTYPE_MENU_ICON_RADIO); - } - else { - wt = widget_type(UI_WTYPE_MENU_RADIO); - } + /* Popover button. */ + wt = popover_widget_type(but, rect); } break; @@ -5322,6 +5336,7 @@ void ui_draw_but(const bContext *C, ARegion *region, uiStyle *style, uiBut *but, uiWidgetStateInfo state = {0}; state.but_flag = but->flag; state.but_drawflag = but->drawflag; + state.emboss = but->emboss; /* Override selected flag for drawing. */ if (but->flag & UI_SELECT_DRAW) {