Refactor: Make UnifiedPaintPanel paint_settings more explicit

The existing `UnifiedPaintPanel.paint_settings` helper function is
commonly used, but has some nuance to the usage that is non-obvious from
the naming. Because it does filtering both on the space type and the
tool system information, there may be cases where it returns `None`
where we otherwise know the correct `Paint` struct to be used.

This commit renames the primary usage to
`paint_settings_from_active_tool` and adds a new overload,
`paint_settings_from_mode`, which can be primarily used in the context
of methods drawing information about specific modes, rather than general
functionality.

Pull Request: https://projects.blender.org/blender/blender/pulls/159826
This commit is contained in:
Sean Kim 2026-06-09 21:01:55 +02:00 • committed by Sean Kim
parent 80c05b2640
commit 8eaee263f6
3 changed files with 44 additions and 38 deletions

View file

@ -131,7 +131,7 @@ class BrushAssetShelf:
if not tool or not tool.use_brushes:
return None
paint_settings = UnifiedPaintPanel.paint_settings(bpy.context)
paint_settings = UnifiedPaintPanel.paint_settings_from_active_tool(bpy.context)
return paint_settings.brush_asset_reference if paint_settings else None
@classmethod
@ -255,12 +255,7 @@ class UnifiedPaintPanel:
return None
@staticmethod
def paint_settings(context):
tool_settings = context.tool_settings
mode = UnifiedPaintPanel.get_brush_mode(context)
# 3D paint settings
def _paint_settings(tool_settings, mode):
if mode == 'SCULPT':
return tool_settings.sculpt
elif mode == 'PAINT_VERTEX':
@ -271,12 +266,10 @@ class UnifiedPaintPanel:
return tool_settings.image_paint
elif mode == 'PARTICLE':
return tool_settings.particle_edit
# 2D paint settings
elif mode == 'PAINT_2D':
return tool_settings.image_paint
elif mode == 'SCULPT_CURVES':
return tool_settings.curves_sculpt
# Grease Pencil settings
elif mode == 'PAINT_GREASE_PENCIL':
return tool_settings.gpencil_paint
elif mode == 'SCULPT_GREASE_PENCIL':
@ -287,6 +280,19 @@ class UnifiedPaintPanel:
return tool_settings.gpencil_vertex_paint
return None
@staticmethod
def paint_settings_from_active_tool(context):
"""Retrieve the Paint settings based on the current active tool, may return None for tools with no associated
brush"""
tool_settings = context.tool_settings
mode = UnifiedPaintPanel.get_brush_mode(context)
return UnifiedPaintPanel._paint_settings(tool_settings, mode)
@staticmethod
def paint_settings_from_mode(context, mode):
"""Retrieve the Paint settings based on a hardcoded 'mode' string."""
return UnifiedPaintPanel._paint_settings(context.tool_settings, mode)
@staticmethod
def prop_unified(
layout,
@ -309,7 +315,7 @@ class UnifiedPaintPanel:
if unified_paint_settings_override:
ups = unified_paint_settings_override
else:
ups = UnifiedPaintPanel.paint_settings(context).unified_paint_settings
ups = UnifiedPaintPanel.paint_settings_from_active_tool(context).unified_paint_settings
prop_owner = brush
if unified_name and getattr(ups, unified_name):
prop_owner = ups
@ -336,7 +342,7 @@ class UnifiedPaintPanel:
curve_visibility_name,
custom_curve_name,
):
paint = UnifiedPaintPanel.paint_settings(context)
paint = UnifiedPaintPanel.paint_settings_from_active_tool(context)
is_active = getattr(paint, curve_visibility_name)
parent_row.prop(
@ -353,13 +359,13 @@ class UnifiedPaintPanel:
@staticmethod
def prop_unified_color(parent, context, brush, prop_name, *, text=None):
ups = UnifiedPaintPanel.paint_settings(context).unified_paint_settings
ups = UnifiedPaintPanel.paint_settings_from_active_tool(context).unified_paint_settings
prop_owner = ups if ups.use_unified_color else brush
parent.prop(prop_owner, prop_name, text=text)
@staticmethod
def prop_unified_color_picker(parent, context, brush, prop_name, value_slider=True):
ups = UnifiedPaintPanel.paint_settings(context).unified_paint_settings
ups = UnifiedPaintPanel.paint_settings_from_active_tool(context).unified_paint_settings
prop_owner = ups if ups.use_unified_color else brush
parent.template_color_picker(prop_owner, prop_name, value_slider=value_slider)
@ -378,7 +384,7 @@ class BrushSelectPanel(BrushPanel):
def draw_header_preset(self, context):
# layout = self.layout # UNUSED.
settings = self.paint_settings(context)
settings = self.paint_settings_from_active_tool(context)
if settings is None:
return
@ -393,7 +399,7 @@ class BrushSelectPanel(BrushPanel):
def draw(self, context):
layout = self.layout
settings = self.paint_settings(context)
settings = self.paint_settings_from_active_tool(context)
if settings is None:
return
@ -422,7 +428,7 @@ class ColorPalettePanel(BrushPanel):
if not super().poll(context):
return False
settings = cls.paint_settings(context)
settings = cls.paint_settings_from_active_tool(context)
if (brush := settings.brush) is None:
return False
@ -441,7 +447,7 @@ class ColorPalettePanel(BrushPanel):
def draw(self, context):
layout = self.layout
settings = self.paint_settings(context)
settings = self.paint_settings_from_active_tool(context)
layout.template_ID(settings, "palette", new="palette.new")
if settings.palette:
@ -457,7 +463,7 @@ class ClonePanel(BrushPanel):
if not super().poll(context):
return False
settings = cls.paint_settings(context)
settings = cls.paint_settings_from_active_tool(context)
mode = cls.get_brush_mode(context)
if mode == 'PAINT_TEXTURE':
@ -466,12 +472,12 @@ class ClonePanel(BrushPanel):
return False
def draw_header(self, context):
settings = self.paint_settings(context)
settings = self.paint_settings_from_active_tool(context)
self.layout.prop(settings, "use_clone_layer", text="")
def draw(self, context):
layout = self.layout
settings = self.paint_settings(context)
settings = self.paint_settings_from_active_tool(context)
layout.active = settings.use_clone_layer
@ -561,7 +567,7 @@ class StrokePanel(BrushPanel):
layout.use_property_decorate = False
mode = self.get_brush_mode(context)
settings = self.paint_settings(context)
settings = self.paint_settings_from_active_tool(context)
brush = settings.brush
col = layout.column()
@ -645,14 +651,14 @@ class SmoothStrokePanel(BrushPanel):
def poll(cls, context):
if not super().poll(context):
return False
settings = cls.paint_settings(context)
settings = cls.paint_settings_from_active_tool(context)
brush = settings.brush
if brush.brush_capabilities.has_smooth_stroke:
return True
return False
def draw_header(self, context):
settings = self.paint_settings(context)
settings = self.paint_settings_from_active_tool(context)
brush = settings.brush
self.layout.use_property_split = False
@ -663,7 +669,7 @@ class SmoothStrokePanel(BrushPanel):
layout.use_property_split = True
layout.use_property_decorate = False
settings = self.paint_settings(context)
settings = self.paint_settings_from_active_tool(context)
brush = settings.brush
col = layout.column()
@ -680,7 +686,7 @@ class FalloffPanel(BrushPanel):
def poll(cls, context):
if not super().poll(context):
return False
settings = cls.paint_settings(context)
settings = cls.paint_settings_from_active_tool(context)
if not (settings and settings.brush and settings.brush.curve_distance_falloff):
return False
if cls.get_brush_mode(context) == 'SCULPT_CURVES':
@ -691,7 +697,7 @@ class FalloffPanel(BrushPanel):
def draw(self, context):
layout = self.layout
settings = self.paint_settings(context)
settings = self.paint_settings_from_active_tool(context)
mode = self.get_brush_mode(context)
brush = settings.brush
@ -734,7 +740,7 @@ class DisplayPanel(BrushPanel):
bl_options = {'DEFAULT_CLOSED'}
def draw_header(self, context):
settings = self.paint_settings(context)
settings = self.paint_settings_from_active_tool(context)
if settings and not self.is_popover:
self.layout.prop(settings, "show_brush", text="")
@ -744,7 +750,7 @@ class DisplayPanel(BrushPanel):
layout.use_property_decorate = False
mode = self.get_brush_mode(context)
settings = self.paint_settings(context)
settings = self.paint_settings_from_active_tool(context)
brush = settings.brush
tex_slot = brush.texture_slot
tex_slot_mask = brush.mask_texture_slot
@ -915,7 +921,7 @@ def brush_settings(layout, context, brush, popover=False):
layout.separator()
if capabilities.has_color:
ups = UnifiedPaintPanel.paint_settings(context).unified_paint_settings
ups = UnifiedPaintPanel.paint_settings_from_mode(context, 'SCULPT').unified_paint_settings
row = layout.row(align=True)
UnifiedPaintPanel.prop_unified_color(row, context, brush, "color", text="")
UnifiedPaintPanel.prop_unified_color(row, context, brush, "secondary_color", text="")
@ -1208,7 +1214,7 @@ def brush_shared_settings(layout, context, brush, popover=False):
size_pressure = True
### Draw settings. ###
ups = UnifiedPaintPanel.paint_settings(context).unified_paint_settings
ups = UnifiedPaintPanel.paint_settings_from_active_tool(context).unified_paint_settings
if blend_mode:
layout.prop(brush, "blend", text="Blend")
@ -1295,7 +1301,7 @@ def brush_shared_settings(layout, context, brush, popover=False):
def draw_color_jitter_panel(layout, context, brush):
ups = UnifiedPaintPanel.paint_settings(context).unified_paint_settings
ups = UnifiedPaintPanel.paint_settings_from_active_tool(context).unified_paint_settings
prop_owner = ups if ups.use_unified_color else brush
layout.use_property_split = False
@ -1526,7 +1532,7 @@ def draw_auto_masking_panel(layout, brush):
def draw_color_settings(context, layout, brush, color_type=False):
"""Draw color wheel and gradient settings."""
ups = UnifiedPaintPanel.paint_settings(context).unified_paint_settings
ups = UnifiedPaintPanel.paint_settings_from_active_tool(context).unified_paint_settings
if color_type:
row = layout.row()

View file

@ -746,7 +746,7 @@ class VIEW3D_HT_header(Header):
show_snap = True
else:
paint_settings = UnifiedPaintPanel.paint_settings(context)
paint_settings = UnifiedPaintPanel.paint_settings_from_active_tool(context)
if paint_settings:
brush = paint_settings.brush
@ -9109,7 +9109,7 @@ class VIEW3D_PT_curves_sculpt_add_shape(Panel):
layout.use_property_split = True
layout.use_property_decorate = False # No animation.
settings = UnifiedPaintPanel.paint_settings(context)
settings = UnifiedPaintPanel.paint_settings_from_mode(context, 'SCULPT_CURVES')
brush = settings.brush
col = layout.column(heading="Interpolate", align=True)
@ -9140,7 +9140,7 @@ class VIEW3D_PT_curves_sculpt_parameter_falloff(Panel):
def draw(self, context):
layout = self.layout
settings = UnifiedPaintPanel.paint_settings(context)
settings = UnifiedPaintPanel.paint_settings_from_mode(context, 'SCULPT_CURVES')
brush = settings.brush
layout.template_curve_mapping(
@ -9164,7 +9164,7 @@ class VIEW3D_PT_curves_sculpt_grow_shrink_scaling(Panel):
layout.use_property_split = True
layout.use_property_decorate = False # No animation.
settings = UnifiedPaintPanel.paint_settings(context)
settings = UnifiedPaintPanel.paint_settings_from_active_tool(context)
brush = settings.brush
layout.prop(brush.curves_sculpt_settings, "use_uniform_scale")

View file

@ -39,7 +39,7 @@ class VIEW3D_MT_brush_context_menu(Menu):
def draw(self, context):
layout = self.layout
settings = UnifiedPaintPanel.paint_settings(context)
settings = UnifiedPaintPanel.paint_settings_from_active_tool(context)
brush = getattr(settings, "brush", None)
# skip if no active brush
@ -364,7 +364,7 @@ class VIEW3D_PT_tools_brush_settings_advanced(Panel, View3DPaintBrushPanel):
layout.use_property_split = True
layout.use_property_decorate = False # No animation.
settings = UnifiedPaintPanel.paint_settings(context)
settings = UnifiedPaintPanel.paint_settings_from_active_tool(context)
brush = settings.brush
brush_settings_advanced(layout.column(), context, settings, brush, self.is_popover)