Files
test2/scripts/startup/bl_ui/space_properties.py
Richard Antalik bf18e8f814 UI: Filter visible tabs in Properties Editor
This commit allows to specialize or optimize properties editor for
particular workflows by hiding individual tabs. The filtering is done on
editor level, currently in editor options popover panel.

Primary motivation was to allow strip properties to be moved to
properties editor. The filtering is beneficial, as usually it does not
make sense to show strip propeties in modelling workspace and in video
editing workspace other properties would introduce quite a bit of noise.

Ref. #115626

Pull Request: https://projects.blender.org/blender/blender/pulls/115624
2025-04-08 18:43:18 +02:00

186 lines
6.4 KiB
Python

# SPDX-FileCopyrightText: 2009-2023 Blender Authors
#
# SPDX-License-Identifier: GPL-2.0-or-later
from bpy.types import Header, Panel
from rna_prop_ui import PropertyPanel
from . import anim
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
)
def draw(self, context):
layout = self.layout
view = context.space_data
region = context.region
ui_scale = context.preferences.system.ui_scale
layout.template_header()
layout.separator_spacer()
if self._search_poll(context.space_data):
# The following is an ugly attempt to make the search button center-align better visually.
# A dummy icon is inserted that has to be scaled as the available width changes.
content_size_est = 160 * ui_scale
layout_scale = min(1, max(0, (region.width / content_size_est) - 1))
if layout_scale > 0:
row = layout.row()
row.scale_x = layout_scale
row.label(icon='BLANK1')
layout.prop(view, "search_filter", icon='VIEWZOOM', text="")
layout.separator_spacer()
layout.popover(panel="PROPERTIES_PT_options", text="")
class PROPERTIES_PT_navigation_bar(Panel):
bl_space_type = 'PROPERTIES'
bl_region_type = 'NAVIGATION_BAR'
bl_label = "Navigation Bar"
bl_options = {'HIDE_HEADER'}
def draw(self, context):
layout = self.layout
view = context.space_data
layout.scale_x = 1.4
layout.scale_y = 1.4
if view.search_filter:
layout.prop_tabs_enum(
view, "context", data_highlight=view,
property_highlight="tab_search_results", icon_only=True,
)
else:
layout.prop_tabs_enum(view, "context", icon_only=True)
class PROPERTIES_PT_options(Panel):
"""Show options for the properties editor"""
bl_space_type = 'PROPERTIES'
bl_region_type = 'HEADER'
bl_label = "Options"
def draw(self, context):
layout = self.layout
space = context.space_data
col = layout.column()
col.label(text="Sync with Outliner")
col.row().prop(space, "outliner_sync", expand=True)
layout.separator()
layout.use_property_split = True
layout.use_property_decorate = False
col = layout.column(heading="Visible Tabs", align=True)
col.prop(space, "show_properties_tool")
col.prop(space, "show_properties_render")
col.prop(space, "show_properties_output")
col.prop(space, "show_properties_view_layer")
col.prop(space, "show_properties_scene")
col.prop(space, "show_properties_world")
col.prop(space, "show_properties_collection")
col.prop(space, "show_properties_object")
col.prop(space, "show_properties_modifiers")
col.prop(space, "show_properties_effects")
col.prop(space, "show_properties_particles")
col.prop(space, "show_properties_physics")
col.prop(space, "show_properties_constraints")
col.prop(space, "show_properties_data")
col.prop(space, "show_properties_bone")
col.prop(space, "show_properties_bone_constraints")
col.prop(space, "show_properties_material")
col.prop(space, "show_properties_texture")
class PropertiesAnimationMixin:
"""Mix-in class for Animation panels.
This class can be used to show a generic 'Animation' panel for IDs shown in
the properties editor. Specific ID types need specific subclasses.
For an example, see DATA_PT_camera_animation in properties_data_camera.py
"""
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "data"
bl_label = "Animation"
bl_options = {'DEFAULT_CLOSED'}
bl_order = PropertyPanel.bl_order - 1 # Order just above the Custom Properties.
_animated_id_context_property = ""
"""context.{_animatable_id_context_property} is used to find the animated ID."""
@classmethod
def _animated_id(cls, context):
assert cls._animated_id_context_property, "set _animated_id_context_property on {!r}".format(cls)
# If the pinned ID is of a different type, there could still be a an ID
# for which to show this panel. For example, a camera object can be
# pinned, and then this panel can be shown for its camera data.
return getattr(context, cls._animated_id_context_property, None)
@classmethod
def poll(cls, context):
animated_id = cls._animated_id(context)
return animated_id is not None
def draw(self, context):
layout = self.layout
col = layout.column(align=True)
col.use_property_split = True
col.use_property_decorate = False
self.draw_action_and_slot_selector(context, col, self._animated_id(context))
@classmethod
def draw_action_and_slot_selector(cls, context, layout, animated_id):
if not animated_id:
class_list = [c.__name__ for c in cls.mro()]
print("PropertiesAnimationMixin: no animatable data-block, this is a bug "
"in one of these classes: {!r}".format(class_list))
layout.label(text="No animatable data-block, please report as bug", icon='ERROR')
return
anim.draw_action_and_slot_selector_for_id(layout, animated_id)
classes = (
PROPERTIES_HT_header,
PROPERTIES_PT_navigation_bar,
PROPERTIES_PT_options,
)
if __name__ == "__main__": # only for live edit.
from bpy.utils import register_class
for cls in classes:
register_class(cls)