From 5b02341a11286bbf29384640843dfebfafd5a024 Mon Sep 17 00:00:00 2001 From: Sean Kim Date: Mon, 15 Sep 2025 14:45:50 +0200 Subject: [PATCH] UI: Add ability to collapse paint pressure curves This commit builds off of 5f8311f596 to support collapsing the custom paint curve to reduce the amount of information shown to the user. To support this, a new field is added to the `Paint` struct for this visibility flag. This value is stored on a per-mode level, not a per-brush level, as a user editing this curve is likely to not need the visibility granularity on a per-brush basis. Additionally, changes are included here to draw the curve button itself as inactive if the parent layout it is part of is inactive. Notably, this does not make the curve read only - it only changes the appearance. Pull Request: https://projects.blender.org/blender/blender/pulls/145699 --- .../startup/bl_ui/properties_paint_common.py | 47 +++++++++++++++---- .../editors/interface/interface_draw.cc | 38 ++++++++++----- .../interface_template_curve_mapping.cc | 3 ++ source/blender/makesdna/DNA_scene_enums.h | 7 +++ source/blender/makesdna/DNA_scene_types.h | 6 +++ .../makesrna/intern/rna_sculpt_paint.cc | 16 +++++++ 6 files changed, 96 insertions(+), 21 deletions(-) diff --git a/scripts/startup/bl_ui/properties_paint_common.py b/scripts/startup/bl_ui/properties_paint_common.py index 98aa02ff808..f69dad5bf91 100644 --- a/scripts/startup/bl_ui/properties_paint_common.py +++ b/scripts/startup/bl_ui/properties_paint_common.py @@ -261,6 +261,7 @@ class UnifiedPaintPanel: unified_paint_settings_override=None, unified_name=None, pressure_name=None, + curve_visibility_name=None, icon='NONE', text=None, slider=False, @@ -272,6 +273,7 @@ class UnifiedPaintPanel: :param unified_paint_settings_override allows a caller to pass in a specific object for usage. Needed for some 'brush-like' tools.""" row = layout.row(align=True) + paint = UnifiedPaintPanel.paint_settings(context) if unified_paint_settings_override: ups = unified_paint_settings_override else: @@ -282,13 +284,21 @@ class UnifiedPaintPanel: row.prop(prop_owner, prop_name, icon=icon, text=text, slider=slider) - if pressure_name: - row.prop(brush, pressure_name, text="") - if unified_name and not header: # NOTE: We don't draw UnifiedPaintSettings in the header to reduce clutter. D5928#136281 row.prop(ups, unified_name, text="", icon='BRUSHES_ALL') + if pressure_name: + row.prop(brush, pressure_name, text="") + + if curve_visibility_name and not header: + is_active = getattr(paint, curve_visibility_name) + row.prop( + paint, + curve_visibility_name, + text="", + icon='DOWNARROW_HLT' if is_active else 'RIGHTARROW', + emboss=False) return row @staticmethod @@ -551,10 +561,19 @@ class StrokePanel(BrushPanel): else: row.prop(brush, "jitter_absolute") row.prop(brush, "use_pressure_jitter", toggle=True, text="") - col.row().prop(brush, "jitter_unit", expand=True) + if self.is_popover is False: + row.prop( + settings, + "show_jitter_curve", + icon='DOWNARROW_HLT' if settings.show_jitter_curve else 'RIGHTARROW', + text="", + emboss=False) # Pen pressure mapping curve for Jitter. - if brush.use_pressure_jitter and self.is_popover is False: - col.template_curve_mapping(brush, "curve_jitter", brush=True) + if settings.show_jitter_curve and self.is_popover is False: + subcol = col.column() + subcol.active = brush.use_pressure_jitter + subcol.template_curve_mapping(brush, "curve_jitter", brush=True) + col.row().prop(brush, "jitter_unit", expand=True) col.separator() UnifiedPaintPanel.prop_unified( @@ -1052,6 +1071,7 @@ def brush_settings(layout, context, brush, popover=False): def brush_shared_settings(layout, context, brush, popover=False): """ Draw simple brush settings that are shared between different paint modes. """ + paint = UnifiedPaintPanel.paint_settings(context) mode = UnifiedPaintPanel.get_brush_mode(context) ### Determine which settings to draw. ### @@ -1146,18 +1166,22 @@ def brush_shared_settings(layout, context, brush, popover=False): size_prop, unified_name="use_unified_size", pressure_name="use_pressure_size", + curve_visibility_name="show_size_curve", text="Size", slider=True, ) if mode in {'PAINT_TEXTURE', 'PAINT_2D', 'SCULPT', 'PAINT_VERTEX', 'PAINT_WEIGHT', 'SCULPT_CURVES'}: - if brush.use_pressure_size: - layout.template_curve_mapping(brush, "curve_size", brush=True) + if paint.show_size_curve and not popover: + subcol = layout.column() + subcol.active = brush.use_pressure_size + subcol.template_curve_mapping(brush, "curve_size", brush=True) if size_mode: layout.row().prop(size_owner, "use_locked_size", expand=True) layout.separator() if strength: pressure_name = "use_pressure_strength" if strength_pressure else None + curve_visibility_name = "show_strength_curve" if strength_pressure else None UnifiedPaintPanel.prop_unified( layout, context, @@ -1165,11 +1189,14 @@ def brush_shared_settings(layout, context, brush, popover=False): "strength", unified_name="use_unified_strength", pressure_name=pressure_name, + curve_visibility_name=curve_visibility_name, slider=True, ) if mode in {'PAINT_TEXTURE', 'PAINT_2D', 'SCULPT', 'PAINT_VERTEX', 'PAINT_WEIGHT', 'SCULPT_CURVES'}: - if strength_pressure and brush.use_pressure_strength: - layout.template_curve_mapping(brush, "curve_strength", brush=True) + if paint.show_strength_curve and not popover: + subcol = layout.column() + subcol.active = brush.use_pressure_strength + subcol.template_curve_mapping(brush, "curve_strength", brush=True) layout.separator() if direction: diff --git a/source/blender/editors/interface/interface_draw.cc b/source/blender/editors/interface/interface_draw.cc index c5f05e39645..588b4b457c0 100644 --- a/source/blender/editors/interface/interface_draw.cc +++ b/source/blender/editors/interface/interface_draw.cc @@ -1616,12 +1616,23 @@ static void gl_shaded_color(const uchar *color, int shade) immUniformColor3ubv(color_shaded); } +static void gl_shaded_color(const uchar *color, int shade, uchar alpha) +{ + uchar color_shaded[3]; + gl_shaded_color_get(color, shade, color_shaded); + immUniformColor3ubvAlpha(color_shaded, alpha); +} + void ui_draw_but_CURVE(ARegion *region, uiBut *but, const uiWidgetColors *wcol, const rcti *rect) { uiButCurveMapping *but_cumap = (uiButCurveMapping *)but; CurveMapping *cumap = (but_cumap->edit_cumap == nullptr) ? (CurveMapping *)but->poin : but_cumap->edit_cumap; + const bool inactive = but->flag & UI_BUT_INACTIVE; + const uchar alpha = inactive ? 192 : 255; + const float float_alpha = inactive ? 0.75f : 1.0f; + const float clip_size_x = BLI_rctf_size_x(&cumap->curr); const float clip_size_y = BLI_rctf_size_y(&cumap->curr); @@ -1682,20 +1693,19 @@ void ui_draw_but_CURVE(ARegion *region, uiBut *but, const uiWidgetColors *wcol, /* backdrop */ float color_backdrop[4] = {0, 0, 0, 1}; + GPU_blend(GPU_BLEND_ALPHA); if (but_cumap->gradient_type == UI_GRAD_H) { /* grid, hsv uses different grid */ - GPU_blend(GPU_BLEND_ALPHA); ARRAY_SET_ITEMS(color_backdrop, 0, 0, 0, 48.0 / 255.0); immUniformColor4fv(color_backdrop); ui_draw_but_curve_grid(pos, rect, zoomx, zoomy, offsx, offsy, 0.1666666f); - GPU_blend(GPU_BLEND_NONE); } else { if (cumap->flag & CUMA_DO_CLIP) { gl_shaded_color_get_fl(wcol->inner, -20, color_backdrop); - immUniformColor3fv(color_backdrop); + immUniformColor3fvAlpha(color_backdrop, float_alpha); immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax); - immUniformColor3ubv(wcol->inner); + immUniformColor3ubvAlpha(wcol->inner, alpha); immRectf(pos, rect->xmin + zoomx * (cumap->clipr.xmin - offsx), rect->ymin + zoomy * (cumap->clipr.ymin - offsy), @@ -1704,18 +1714,18 @@ void ui_draw_but_CURVE(ARegion *region, uiBut *but, const uiWidgetColors *wcol, } else { rgb_uchar_to_float(color_backdrop, wcol->inner); - immUniformColor3fv(color_backdrop); + immUniformColor3fvAlpha(color_backdrop, float_alpha); immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax); } /* grid, every 0.25 step */ - gl_shaded_color(wcol->inner, -16); + gl_shaded_color(wcol->inner, -16, alpha); ui_draw_but_curve_grid(pos, rect, zoomx, zoomy, offsx, offsy, 0.25f); /* grid, every 1.0 step */ - gl_shaded_color(wcol->inner, -24); + gl_shaded_color(wcol->inner, -24, alpha); ui_draw_but_curve_grid(pos, rect, zoomx, zoomy, offsx, offsy, 1.0f); /* axes */ - gl_shaded_color(wcol->inner, -50); + gl_shaded_color(wcol->inner, -50, alpha); immBegin(GPU_PRIM_LINES, 4); immVertex2f(pos, rect->xmin, rect->ymin + zoomy * (-offsy)); immVertex2f(pos, rect->xmax, rect->ymin + zoomy * (-offsy)); @@ -1723,6 +1733,7 @@ void ui_draw_but_CURVE(ARegion *region, uiBut *but, const uiWidgetColors *wcol, immVertex2f(pos, rect->xmin + zoomx * (-offsx), rect->ymax); immEnd(); } + GPU_blend(GPU_BLEND_NONE); /* cfra option */ /* XXX 2.48 */ @@ -1800,11 +1811,12 @@ void ui_draw_but_CURVE(ARegion *region, uiBut *but, const uiWidgetColors *wcol, line_range.ymax = rect->ymin + zoomy * (cmp[CM_TABLE].y - offsy - cuma->ext_out[1]); } - immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); GPU_blend(GPU_BLEND_ALPHA); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); /* Curve filled. */ - immUniformColor3ubvAlpha(wcol->item, 128); + uchar filled_alpha = inactive ? 64 : 128; + immUniformColor3ubvAlpha(wcol->item, filled_alpha); immBegin(GPU_PRIM_TRI_STRIP, (CM_TABLE * 2 + 2) + 4); immVertex2f(pos, line_range.xmin, rect->ymin); immVertex2f(pos, line_range.xmin, line_range.ymin); @@ -1820,7 +1832,7 @@ void ui_draw_but_CURVE(ARegion *region, uiBut *but, const uiWidgetColors *wcol, /* Curve line. */ GPU_line_width(1.0f); - immUniformColor3ubvAlpha(wcol->item, 255); + immUniformColor3ubvAlpha(wcol->item, alpha); GPU_line_smooth(true); immBegin(GPU_PRIM_LINE_STRIP, (CM_TABLE + 1) + 2); immVertex2f(pos, line_range.xmin, line_range.ymin); @@ -1851,6 +1863,10 @@ void ui_draw_but_CURVE(ARegion *region, uiBut *but, const uiWidgetColors *wcol, float color_vert[4], color_vert_select[4]; UI_GetThemeColor4fv(TH_TEXT_HI, color_vert); UI_GetThemeColor4fv(TH_TEXT, color_vert_select); + if (inactive) { + color_vert[3] *= float_alpha; + color_vert_select[3] *= float_alpha; + } if (len_squared_v3v3(color_vert, color_vert_select) < 0.1f) { interp_v3_v3v3(color_vert, color_vert_select, color_backdrop, 0.75f); } diff --git a/source/blender/editors/interface/templates/interface_template_curve_mapping.cc b/source/blender/editors/interface/templates/interface_template_curve_mapping.cc index 05fd0144d39..19c1984f973 100644 --- a/source/blender/editors/interface/templates/interface_template_curve_mapping.cc +++ b/source/blender/editors/interface/templates/interface_template_curve_mapping.cc @@ -580,6 +580,9 @@ static void curvemap_buttons_layout(uiLayout *layout, 1.0f, ""); curve_but->gradient_type = bg; + if (!layout->active()) { + UI_but_flag_enable(curve_but, UI_BUT_INACTIVE); + } /* Sliders for selected curve point. */ int i; diff --git a/source/blender/makesdna/DNA_scene_enums.h b/source/blender/makesdna/DNA_scene_enums.h index 2b71e848223..f9c20d7c6c6 100644 --- a/source/blender/makesdna/DNA_scene_enums.h +++ b/source/blender/makesdna/DNA_scene_enums.h @@ -64,3 +64,10 @@ typedef enum eUnifiedPaintSettingsFlags { UNIFIED_PAINT_INPUT_SAMPLES = (1 << 7), UNIFIED_PAINT_COLOR_JITTER = (1 << 8), } eUnifiedPaintSettingsFlags; + +/** Paint::curve_visibility_flag*/ +typedef enum PaintCurveVisibilityFlags { + PAINT_CURVE_SHOW_STRENGTH = (1 << 0), + PAINT_CURVE_SHOW_SIZE = (1 << 1), + PAINT_CURVE_SHOW_JITTER = (1 << 2), +} PaintCurveVisibilityFlags; diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 1e023598416..189021e8455 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -1189,6 +1189,12 @@ typedef struct Paint { /** Flags used for symmetry. */ int symmetry_flags; + /** + * Collapsed state of a given pressure curve + * See #PaintCurveVisibilityFlags + */ + int curve_visibility_flags; + char _pad[4]; float tile_offset[3]; struct UnifiedPaintSettings unified_paint_settings; diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.cc b/source/blender/makesrna/intern/rna_sculpt_paint.cc index ef501babdd7..90110743ede 100644 --- a/source/blender/makesrna/intern/rna_sculpt_paint.cc +++ b/source/blender/makesrna/intern/rna_sculpt_paint.cc @@ -757,6 +757,22 @@ static void rna_def_paint(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Tile Z", "Tile along Z axis"); RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + prop = RNA_def_property(srna, "show_strength_curve", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna( + prop, nullptr, "curve_visibility_flags", PAINT_CURVE_SHOW_STRENGTH); + RNA_def_property_ui_text(prop, "Show Strength Curve", "Show strength curve"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "show_size_curve", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "curve_visibility_flags", PAINT_CURVE_SHOW_SIZE); + RNA_def_property_ui_text(prop, "Show Size Curve", "Show size curve"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + + prop = RNA_def_property(srna, "show_jitter_curve", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, nullptr, "curve_visibility_flags", PAINT_CURVE_SHOW_JITTER); + RNA_def_property_ui_text(prop, "Show Jitter Curve", "Show jitter curve"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr); + /* Unified Paint Settings */ prop = RNA_def_property(srna, "unified_paint_settings", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL);