Files
test/scripts/startup/bl_ui/space_properties.py
Sybren A. Stüvel ad2207243a Anim: invisible UI tweak for Action and Slot selectors in Properties Editor
Set `use_property_decorate = False` in the Animation panels in the
Properties editor. This has no visual effect right now, but if we ever
decide to add labels to the selectors, this will ensure that the layout
remains correct.

Context: `layout.template_action()` and `layout.template_search()` respond
differently to the default of `use_property_decorate = True`.
2024-09-27 16:33:27 +02:00

155 lines
4.9 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
class PROPERTIES_HT_header(Header):
bl_space_type = 'PROPERTIES'
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()
# 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)
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, f'set _animated_id_context_property on {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: {}".format(class_list))
layout.label(text='No animatable data-block, please report as bug', icon='ERROR')
return
layout.template_action(animated_id, new="action.new", unlink="action.unlink")
if not context.preferences.experimental.use_animation_baklava:
return
adt = animated_id.animation_data
if not adt or not adt.action:
return
# Only show the slot selector when a layered Action is assigned.
if adt.action.is_action_layered:
layout.context_pointer_set("animated_id", animated_id)
layout.template_search(
adt, "action_slot",
adt, "action_slots",
new="anim.slot_new_for_id",
unlink="anim.slot_unassign_from_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)